diff options
Diffstat (limited to 'drivers/i2c')
35 files changed, 868 insertions, 470 deletions
| diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 7bb65a4369e1..72c94c60fdd1 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0  #  # Makefile for the i2c core.  # diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 45a3f3ca29b3..009345d8f49d 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -198,6 +198,11 @@ config I2C_CHT_WC  	  SMBus controller found in the Intel Cherry Trail Whiskey Cove PMIC  	  found on some Intel Cherry Trail systems. +	  Note this controller is hooked up to a TI bq24292i charger-IC, +	  combined with a FUSB302 Type-C port-controller as such it is advised +	  to also select CONFIG_CHARGER_BQ24190=m and CONFIG_TYPEC_FUSB302=m +	  (the fusb302 driver currently is in drivers/staging). +  config I2C_NFORCE2  	tristate "Nvidia nForce2, nForce3 and nForce4"  	depends on PCI diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 47f3ac9a695a..2ce8576540a2 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0  #  # Makefile for the i2c bus drivers.  # diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index 284f8670dbeb..7d4aeb4465b3 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -27,6 +27,7 @@  #include <linux/of_irq.h>  #include <linux/of_platform.h>  #include <linux/platform_device.h> +#include <linux/reset.h>  #include <linux/slab.h>  /* I2C Register */ @@ -132,6 +133,7 @@ struct aspeed_i2c_bus {  	struct i2c_adapter		adap;  	struct device			*dev;  	void __iomem			*base; +	struct reset_control		*rst;  	/* Synchronizes I/O mem access to base. */  	spinlock_t			lock;  	struct completion		cmd_complete; @@ -847,6 +849,14 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)  	/* We just need the clock rate, we don't actually use the clk object. */  	devm_clk_put(&pdev->dev, parent_clk); +	bus->rst = devm_reset_control_get_shared(&pdev->dev, NULL); +	if (IS_ERR(bus->rst)) { +		dev_err(&pdev->dev, +			"missing or invalid reset controller device tree entry"); +		return PTR_ERR(bus->rst); +	} +	reset_control_deassert(bus->rst); +  	ret = of_property_read_u32(pdev->dev.of_node,  				   "bus-frequency", &bus->bus_frequency);  	if (ret < 0) { @@ -917,6 +927,8 @@ static int aspeed_i2c_remove_bus(struct platform_device *pdev)  	spin_unlock_irqrestore(&bus->lock, flags); +	reset_control_assert(bus->rst); +  	i2c_del_adapter(&bus->adap);  	return 0; diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c index 190bbbc7bfee..44cffad43701 100644 --- a/drivers/i2c/busses/i2c-cht-wc.c +++ b/drivers/i2c/busses/i2c-cht-wc.c @@ -16,6 +16,7 @@   * GNU General Public License for more details.   */ +#include <linux/acpi.h>  #include <linux/completion.h>  #include <linux/delay.h>  #include <linux/i2c.h> @@ -25,6 +26,7 @@  #include <linux/mfd/intel_soc_pmic.h>  #include <linux/module.h>  #include <linux/platform_device.h> +#include <linux/power/bq24190_charger.h>  #include <linux/slab.h>  #define CHT_WC_I2C_CTRL			0x5e24 @@ -232,13 +234,35 @@ static const struct irq_chip cht_wc_i2c_irq_chip = {  	.name			= "cht_wc_ext_chrg_irq_chip",  }; +static const char * const bq24190_suppliers[] = { "fusb302-typec-source" }; +  static const struct property_entry bq24190_props[] = { -	PROPERTY_ENTRY_STRING("extcon-name", "cht_wcove_pwrsrc"), +	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq24190_suppliers),  	PROPERTY_ENTRY_BOOL("omit-battery-class"),  	PROPERTY_ENTRY_BOOL("disable-reset"),  	{ }  }; +static struct regulator_consumer_supply fusb302_consumer = { +	.supply = "vbus", +	/* Must match fusb302 dev_name in intel_cht_int33fe.c */ +	.dev_name = "i2c-fusb302", +}; + +static const struct regulator_init_data bq24190_vbus_init_data = { +	.constraints = { +		/* The name is used in intel_cht_int33fe.c do not change. */ +		.name = "cht_wc_usb_typec_vbus", +		.valid_ops_mask = REGULATOR_CHANGE_STATUS, +	}, +	.consumer_supplies = &fusb302_consumer, +	.num_consumer_supplies = 1, +}; + +static struct bq24190_platform_data bq24190_pdata = { +	.regulator_init_data = &bq24190_vbus_init_data, +}; +  static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)  {  	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent); @@ -246,7 +270,9 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)  	struct i2c_board_info board_info = {  		.type = "bq24190",  		.addr = 0x6b, +		.dev_name = "bq24190",  		.properties = bq24190_props, +		.platform_data = &bq24190_pdata,  	};  	int ret, reg, irq; @@ -314,11 +340,21 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)  	if (ret)  		goto remove_irq_domain; -	board_info.irq = adap->client_irq; -	adap->client = i2c_new_device(&adap->adapter, &board_info); -	if (!adap->client) { -		ret = -ENOMEM; -		goto del_adapter; +	/* +	 * Normally the Whiskey Cove PMIC is paired with a TI bq24292i charger, +	 * connected to this i2c bus, and a max17047 fuel-gauge and a fusb302 +	 * USB Type-C controller connected to another i2c bus. In this setup +	 * the max17047 and fusb302 devices are enumerated through an INT33FE +	 * ACPI device. If this device is present register an i2c-client for +	 * the TI bq24292i charger. +	 */ +	if (acpi_dev_present("INT33FE", NULL, -1)) { +		board_info.irq = adap->client_irq; +		adap->client = i2c_new_device(&adap->adapter, &board_info); +		if (!adap->client) { +			ret = -ENOMEM; +			goto del_adapter; +		}  	}  	platform_set_drvdata(pdev, adap); @@ -335,14 +371,15 @@ static int cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev)  {  	struct cht_wc_i2c_adap *adap = platform_get_drvdata(pdev); -	i2c_unregister_device(adap->client); +	if (adap->client) +		i2c_unregister_device(adap->client);  	i2c_del_adapter(&adap->adapter);  	irq_domain_remove(adap->irq_domain);  	return 0;  } -static struct platform_device_id cht_wc_i2c_adap_id_table[] = { +static const struct platform_device_id cht_wc_i2c_adap_id_table[] = {  	{ .name = "cht_wcove_ext_chgr" },  	{},  }; diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index b8c43535f16c..2ead9b9eebb7 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -36,6 +36,7 @@  #include <linux/gpio.h>  #include <linux/of_device.h>  #include <linux/platform_data/i2c-davinci.h> +#include <linux/pm_runtime.h>  /* ----- global defines ----------------------------------------------- */ @@ -122,6 +123,9 @@  /* set the SDA GPIO low */  #define DAVINCI_I2C_DCLR_PDCLR1	BIT(1) +/* timeout for pm runtime autosuspend */ +#define DAVINCI_I2C_PM_TIMEOUT	1000	/* ms */ +  struct davinci_i2c_dev {  	struct device           *dev;  	void __iomem		*base; @@ -500,7 +504,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)  		/* This should be 0 if all bytes were transferred  		 * or dev->cmd_err denotes an error.  		 */ -		dev_err(dev->dev, "abnormal termination buf_len=%i\n", +		dev_err(dev->dev, "abnormal termination buf_len=%zu\n",  			dev->buf_len);  		dev->terminate = 1;  		wmb(); @@ -541,10 +545,17 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)  	dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num); +	ret = pm_runtime_get_sync(dev->dev); +	if (ret < 0) { +		dev_err(dev->dev, "Failed to runtime_get device: %d\n", ret); +		pm_runtime_put_noidle(dev->dev); +		return ret; +	} +  	ret = i2c_davinci_wait_bus_not_busy(dev);  	if (ret < 0) {  		dev_warn(dev->dev, "timeout waiting for bus ready\n"); -		return ret; +		goto out;  	}  	for (i = 0; i < num; i++) { @@ -552,14 +563,19 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)  		dev_dbg(dev->dev, "%s [%d/%d] ret: %d\n", __func__, i + 1, num,  			ret);  		if (ret < 0) -			return ret; +			goto out;  	} +	ret = num;  #ifdef CONFIG_CPU_FREQ  	complete(&dev->xfr_complete);  #endif -	return num; +out: +	pm_runtime_mark_last_busy(dev->dev); +	pm_runtime_put_autosuspend(dev->dev); + +	return ret;  }  static u32 i2c_davinci_func(struct i2c_adapter *adap) @@ -599,6 +615,9 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)  	int count = 0;  	u16 w; +	if (pm_runtime_suspended(dev->dev)) +		return IRQ_NONE; +  	while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) {  		dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);  		if (count++ == 100) { @@ -802,13 +821,24 @@ static int davinci_i2c_probe(struct platform_device *pdev)  	dev->clk = devm_clk_get(&pdev->dev, NULL);  	if (IS_ERR(dev->clk))  		return PTR_ERR(dev->clk); -	clk_prepare_enable(dev->clk);  	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	dev->base = devm_ioremap_resource(&pdev->dev, mem);  	if (IS_ERR(dev->base)) { -		r = PTR_ERR(dev->base); -		goto err_unuse_clocks; +		return PTR_ERR(dev->base); +	} + +	pm_runtime_set_autosuspend_delay(dev->dev, +					 DAVINCI_I2C_PM_TIMEOUT); +	pm_runtime_use_autosuspend(dev->dev); + +	pm_runtime_enable(dev->dev); + +	r = pm_runtime_get_sync(dev->dev); +	if (r < 0) { +		dev_err(dev->dev, "failed to runtime_get device: %d\n", r); +		pm_runtime_put_noidle(dev->dev); +		return r;  	}  	i2c_davinci_init(dev); @@ -849,27 +879,40 @@ static int davinci_i2c_probe(struct platform_device *pdev)  	if (r)  		goto err_unuse_clocks; +	pm_runtime_mark_last_busy(dev->dev); +	pm_runtime_put_autosuspend(dev->dev); +  	return 0;  err_unuse_clocks: -	clk_disable_unprepare(dev->clk); -	dev->clk = NULL; +	pm_runtime_dont_use_autosuspend(dev->dev); +	pm_runtime_put_sync(dev->dev); +	pm_runtime_disable(dev->dev); +  	return r;  }  static int davinci_i2c_remove(struct platform_device *pdev)  {  	struct davinci_i2c_dev *dev = platform_get_drvdata(pdev); +	int ret;  	i2c_davinci_cpufreq_deregister(dev);  	i2c_del_adapter(&dev->adapter); -	clk_disable_unprepare(dev->clk); -	dev->clk = NULL; +	ret = pm_runtime_get_sync(&pdev->dev); +	if (ret < 0) { +		pm_runtime_put_noidle(&pdev->dev); +		return ret; +	}  	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0); +	pm_runtime_dont_use_autosuspend(dev->dev); +	pm_runtime_put_sync(dev->dev); +	pm_runtime_disable(dev->dev); +  	return 0;  } @@ -880,7 +923,6 @@ static int davinci_i2c_suspend(struct device *dev)  	/* put I2C into reset */  	davinci_i2c_reset_ctrl(i2c_dev, 0); -	clk_disable_unprepare(i2c_dev->clk);  	return 0;  } @@ -889,7 +931,6 @@ static int davinci_i2c_resume(struct device *dev)  {  	struct davinci_i2c_dev *i2c_dev = dev_get_drvdata(dev); -	clk_prepare_enable(i2c_dev->clk);  	/* take I2C out of reset */  	davinci_i2c_reset_ctrl(i2c_dev, 1); @@ -899,6 +940,8 @@ static int davinci_i2c_resume(struct device *dev)  static const struct dev_pm_ops davinci_i2c_pm = {  	.suspend        = davinci_i2c_suspend,  	.resume         = davinci_i2c_resume, +	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, +				      pm_runtime_force_resume)  };  #define davinci_i2c_pm_ops (&davinci_i2c_pm) diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index 9fee4c054d3d..21bf619a86c5 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -280,6 +280,8 @@ struct dw_i2c_dev {  	int			(*acquire_lock)(struct dw_i2c_dev *dev);  	void			(*release_lock)(struct dw_i2c_dev *dev);  	bool			pm_disabled; +	bool			suspended; +	bool			skip_resume;  	void			(*disable)(struct dw_i2c_dev *dev);  	void			(*disable_int)(struct dw_i2c_dev *dev);  	int			(*init)(struct dw_i2c_dev *dev); diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 0e65b97842b4..58add69a441c 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -249,6 +249,14 @@ static void dw_i2c_set_fifo_size(struct dw_i2c_dev *dev, int id)  	}  } +static void dw_i2c_plat_pm_cleanup(struct dw_i2c_dev *dev) +{ +	pm_runtime_disable(dev->dev); + +	if (dev->pm_disabled) +		pm_runtime_put_noidle(dev->dev); +} +  static int dw_i2c_plat_probe(struct platform_device *pdev)  {  	struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev); @@ -257,7 +265,9 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)  	u32 acpi_speed, ht = 0;  	struct resource *mem;  	int i, irq, ret; -	const int supported_speeds[] = { 0, 100000, 400000, 1000000, 3400000 }; +	static const int supported_speeds[] = { +		0, 100000, 400000, 1000000, 3400000 +	};  	irq = platform_get_irq(pdev, 0);  	if (irq < 0) @@ -362,14 +372,17 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)  	ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev));  	adap->dev.of_node = pdev->dev.of_node; -	if (dev->pm_disabled) { -		pm_runtime_forbid(&pdev->dev); -	} else { -		pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); -		pm_runtime_use_autosuspend(&pdev->dev); -		pm_runtime_set_active(&pdev->dev); -		pm_runtime_enable(&pdev->dev); -	} +	/* The code below assumes runtime PM to be disabled. */ +	WARN_ON(pm_runtime_enabled(&pdev->dev)); + +	pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); +	pm_runtime_use_autosuspend(&pdev->dev); +	pm_runtime_set_active(&pdev->dev); + +	if (dev->pm_disabled) +		pm_runtime_get_noresume(&pdev->dev); + +	pm_runtime_enable(&pdev->dev);  	if (dev->mode == DW_IC_SLAVE)  		ret = i2c_dw_probe_slave(dev); @@ -382,8 +395,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)  	return ret;  exit_probe: -	if (!dev->pm_disabled) -		pm_runtime_disable(&pdev->dev); +	dw_i2c_plat_pm_cleanup(dev);  exit_reset:  	if (!IS_ERR_OR_NULL(dev->rst))  		reset_control_assert(dev->rst); @@ -402,8 +414,8 @@ static int dw_i2c_plat_remove(struct platform_device *pdev)  	pm_runtime_dont_use_autosuspend(&pdev->dev);  	pm_runtime_put_sync(&pdev->dev); -	if (!dev->pm_disabled) -		pm_runtime_disable(&pdev->dev); +	dw_i2c_plat_pm_cleanup(dev); +  	if (!IS_ERR_OR_NULL(dev->rst))  		reset_control_assert(dev->rst); @@ -437,13 +449,20 @@ static void dw_i2c_plat_complete(struct device *dev)  #endif  #ifdef CONFIG_PM -static int dw_i2c_plat_runtime_suspend(struct device *dev) +static int dw_i2c_plat_suspend(struct device *dev)  {  	struct dw_i2c_dev *i_dev = dev_get_drvdata(dev); +	if (i_dev->suspended) { +		i_dev->skip_resume = true; +		return 0; +	} +  	i_dev->disable(i_dev);  	i2c_dw_plat_prepare_clk(i_dev, false); +	i_dev->suspended = true; +  	return 0;  } @@ -451,27 +470,27 @@ static int dw_i2c_plat_resume(struct device *dev)  {  	struct dw_i2c_dev *i_dev = dev_get_drvdata(dev); +	if (!i_dev->suspended) +		return 0; + +	if (i_dev->skip_resume) { +		i_dev->skip_resume = false; +		return 0; +	} +  	i2c_dw_plat_prepare_clk(i_dev, true);  	i_dev->init(i_dev); -	return 0; -} +	i_dev->suspended = false; -#ifdef CONFIG_PM_SLEEP -static int dw_i2c_plat_suspend(struct device *dev) -{ -	pm_runtime_resume(dev); -	return dw_i2c_plat_runtime_suspend(dev); +	return 0;  } -#endif  static const struct dev_pm_ops dw_i2c_dev_pm_ops = {  	.prepare = dw_i2c_plat_prepare,  	.complete = dw_i2c_plat_complete, -	SET_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume) -	SET_RUNTIME_PM_OPS(dw_i2c_plat_runtime_suspend, -			   dw_i2c_plat_resume, -			   NULL) +	SET_LATE_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume) +	SET_RUNTIME_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume, NULL)  };  #define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops) diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index 0ef8fcc6ac3a..d80ea6ce91bb 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -14,27 +14,17 @@  #include <linux/module.h>  #include <linux/slab.h>  #include <linux/platform_device.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h>  #include <linux/of.h> -#include <linux/of_gpio.h>  struct i2c_gpio_private_data { +	struct gpio_desc *sda; +	struct gpio_desc *scl;  	struct i2c_adapter adap;  	struct i2c_algo_bit_data bit_data;  	struct i2c_gpio_platform_data pdata;  }; -/* Toggle SDA by changing the direction of the pin */ -static void i2c_gpio_setsda_dir(void *data, int state) -{ -	struct i2c_gpio_platform_data *pdata = data; - -	if (state) -		gpio_direction_input(pdata->sda_pin); -	else -		gpio_direction_output(pdata->sda_pin, 0); -} -  /*   * Toggle SDA by changing the output value of the pin. This is only   * valid for pins configured as open drain (i.e. setting the value @@ -42,20 +32,9 @@ static void i2c_gpio_setsda_dir(void *data, int state)   */  static void i2c_gpio_setsda_val(void *data, int state)  { -	struct i2c_gpio_platform_data *pdata = data; - -	gpio_set_value(pdata->sda_pin, state); -} - -/* Toggle SCL by changing the direction of the pin. */ -static void i2c_gpio_setscl_dir(void *data, int state) -{ -	struct i2c_gpio_platform_data *pdata = data; +	struct i2c_gpio_private_data *priv = data; -	if (state) -		gpio_direction_input(pdata->scl_pin); -	else -		gpio_direction_output(pdata->scl_pin, 0); +	gpiod_set_value(priv->sda, state);  }  /* @@ -66,44 +45,23 @@ static void i2c_gpio_setscl_dir(void *data, int state)   */  static void i2c_gpio_setscl_val(void *data, int state)  { -	struct i2c_gpio_platform_data *pdata = data; +	struct i2c_gpio_private_data *priv = data; -	gpio_set_value(pdata->scl_pin, state); +	gpiod_set_value(priv->scl, state);  }  static int i2c_gpio_getsda(void *data)  { -	struct i2c_gpio_platform_data *pdata = data; +	struct i2c_gpio_private_data *priv = data; -	return gpio_get_value(pdata->sda_pin); +	return gpiod_get_value(priv->sda);  }  static int i2c_gpio_getscl(void *data)  { -	struct i2c_gpio_platform_data *pdata = data; - -	return gpio_get_value(pdata->scl_pin); -} - -static int of_i2c_gpio_get_pins(struct device_node *np, -				unsigned int *sda_pin, unsigned int *scl_pin) -{ -	if (of_gpio_count(np) < 2) -		return -ENODEV; - -	*sda_pin = of_get_gpio(np, 0); -	*scl_pin = of_get_gpio(np, 1); - -	if (*sda_pin == -EPROBE_DEFER || *scl_pin == -EPROBE_DEFER) -		return -EPROBE_DEFER; - -	if (!gpio_is_valid(*sda_pin) || !gpio_is_valid(*scl_pin)) { -		pr_err("%pOF: invalid GPIO pins, sda=%d/scl=%d\n", -		       np, *sda_pin, *scl_pin); -		return -ENODEV; -	} +	struct i2c_gpio_private_data *priv = data; -	return 0; +	return gpiod_get_value(priv->scl);  }  static void of_i2c_gpio_get_props(struct device_node *np, @@ -124,72 +82,105 @@ static void of_i2c_gpio_get_props(struct device_node *np,  		of_property_read_bool(np, "i2c-gpio,scl-output-only");  } +static struct gpio_desc *i2c_gpio_get_desc(struct device *dev, +					   const char *con_id, +					   unsigned int index, +					   enum gpiod_flags gflags) +{ +	struct gpio_desc *retdesc; +	int ret; + +	retdesc = devm_gpiod_get(dev, con_id, gflags); +	if (!IS_ERR(retdesc)) { +		dev_dbg(dev, "got GPIO from name %s\n", con_id); +		return retdesc; +	} + +	retdesc = devm_gpiod_get_index(dev, NULL, index, gflags); +	if (!IS_ERR(retdesc)) { +		dev_dbg(dev, "got GPIO from index %u\n", index); +		return retdesc; +	} + +	ret = PTR_ERR(retdesc); + +	/* FIXME: hack in the old code, is this really necessary? */ +	if (ret == -EINVAL) +		retdesc = ERR_PTR(-EPROBE_DEFER); + +	/* This happens if the GPIO driver is not yet probed, let's defer */ +	if (ret == -ENOENT) +		retdesc = ERR_PTR(-EPROBE_DEFER); + +	if (ret != -EPROBE_DEFER) +		dev_err(dev, "error trying to get descriptor: %d\n", ret); + +	return retdesc; +} +  static int i2c_gpio_probe(struct platform_device *pdev)  {  	struct i2c_gpio_private_data *priv;  	struct i2c_gpio_platform_data *pdata;  	struct i2c_algo_bit_data *bit_data;  	struct i2c_adapter *adap; -	unsigned int sda_pin, scl_pin; +	struct device *dev = &pdev->dev; +	struct device_node *np = dev->of_node; +	enum gpiod_flags gflags;  	int ret; -	/* First get the GPIO pins; if it fails, we'll defer the probe. */ -	if (pdev->dev.of_node) { -		ret = of_i2c_gpio_get_pins(pdev->dev.of_node, -					   &sda_pin, &scl_pin); -		if (ret) -			return ret; -	} else { -		if (!dev_get_platdata(&pdev->dev)) -			return -ENXIO; -		pdata = dev_get_platdata(&pdev->dev); -		sda_pin = pdata->sda_pin; -		scl_pin = pdata->scl_pin; -	} - -	ret = devm_gpio_request(&pdev->dev, sda_pin, "sda"); -	if (ret) { -		if (ret == -EINVAL) -			ret = -EPROBE_DEFER;	/* Try again later */ -		return ret; -	} -	ret = devm_gpio_request(&pdev->dev, scl_pin, "scl"); -	if (ret) { -		if (ret == -EINVAL) -			ret = -EPROBE_DEFER;	/* Try again later */ -		return ret; -	} - -	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);  	if (!priv)  		return -ENOMEM; +  	adap = &priv->adap;  	bit_data = &priv->bit_data;  	pdata = &priv->pdata; -	if (pdev->dev.of_node) { -		pdata->sda_pin = sda_pin; -		pdata->scl_pin = scl_pin; -		of_i2c_gpio_get_props(pdev->dev.of_node, pdata); +	if (np) { +		of_i2c_gpio_get_props(np, pdata);  	} else { -		memcpy(pdata, dev_get_platdata(&pdev->dev), sizeof(*pdata)); +		/* +		 * If all platform data settings are zero it is OK +		 * to not provide any platform data from the board. +		 */ +		if (dev_get_platdata(dev)) +			memcpy(pdata, dev_get_platdata(dev), sizeof(*pdata));  	} -	if (pdata->sda_is_open_drain) { -		gpio_direction_output(pdata->sda_pin, 1); -		bit_data->setsda = i2c_gpio_setsda_val; -	} else { -		gpio_direction_input(pdata->sda_pin); -		bit_data->setsda = i2c_gpio_setsda_dir; -	} +	/* +	 * First get the GPIO pins; if it fails, we'll defer the probe. +	 * If the SDA line is marked from platform data or device tree as +	 * "open drain" it means something outside of our control is making +	 * this line being handled as open drain, and we should just handle +	 * it as any other output. Else we enforce open drain as this is +	 * required for an I2C bus. +	 */ +	if (pdata->sda_is_open_drain) +		gflags = GPIOD_OUT_HIGH; +	else +		gflags = GPIOD_OUT_HIGH_OPEN_DRAIN; +	priv->sda = i2c_gpio_get_desc(dev, "sda", 0, gflags); +	if (IS_ERR(priv->sda)) +		return PTR_ERR(priv->sda); + +	/* +	 * If the SCL line is marked from platform data or device tree as +	 * "open drain" it means something outside of our control is making +	 * this line being handled as open drain, and we should just handle +	 * it as any other output. Else we enforce open drain as this is +	 * required for an I2C bus. +	 */ +	if (pdata->scl_is_open_drain) +		gflags = GPIOD_OUT_LOW; +	else +		gflags = GPIOD_OUT_LOW_OPEN_DRAIN; +	priv->scl = i2c_gpio_get_desc(dev, "scl", 1, gflags); +	if (IS_ERR(priv->scl)) +		return PTR_ERR(priv->scl); -	if (pdata->scl_is_open_drain || pdata->scl_is_output_only) { -		gpio_direction_output(pdata->scl_pin, 1); -		bit_data->setscl = i2c_gpio_setscl_val; -	} else { -		gpio_direction_input(pdata->scl_pin); -		bit_data->setscl = i2c_gpio_setscl_dir; -	} +	bit_data->setsda = i2c_gpio_setsda_val; +	bit_data->setscl = i2c_gpio_setscl_val;  	if (!pdata->scl_is_output_only)  		bit_data->getscl = i2c_gpio_getscl; @@ -207,18 +198,18 @@ static int i2c_gpio_probe(struct platform_device *pdev)  	else  		bit_data->timeout = HZ / 10;		/* 100 ms */ -	bit_data->data = pdata; +	bit_data->data = priv;  	adap->owner = THIS_MODULE; -	if (pdev->dev.of_node) -		strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); +	if (np) +		strlcpy(adap->name, dev_name(dev), sizeof(adap->name));  	else  		snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);  	adap->algo_data = bit_data;  	adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; -	adap->dev.parent = &pdev->dev; -	adap->dev.of_node = pdev->dev.of_node; +	adap->dev.parent = dev; +	adap->dev.of_node = np;  	adap->nr = pdev->id;  	ret = i2c_bit_add_numbered_bus(adap); @@ -227,8 +218,13 @@ static int i2c_gpio_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, priv); -	dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n", -		 pdata->sda_pin, pdata->scl_pin, +	/* +	 * FIXME: using global GPIO numbers is not helpful. If/when we +	 * get accessors to get the actual name of the GPIO line, +	 * from the descriptor, then provide that instead. +	 */ +	dev_info(dev, "using lines %u (SDA) and %u (SCL%s)\n", +		 desc_to_gpio(priv->sda), desc_to_gpio(priv->scl),  		 pdata->scl_is_output_only  		 ? ", no clock stretching" : ""); diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 9e12a53ef7b8..8eac00efadc1 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1617,6 +1617,9 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)  	/* Default timeout in interrupt mode: 200 ms */  	priv->adapter.timeout = HZ / 5; +	if (dev->irq == IRQ_NOTCONNECTED) +		priv->features &= ~FEATURE_IRQ; +  	if (priv->features & FEATURE_IRQ) {  		u16 pcictl, pcists; diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c index eb1d91b986fd..f038858b6c54 100644 --- a/drivers/i2c/busses/i2c-img-scb.c +++ b/drivers/i2c/busses/i2c-img-scb.c @@ -82,6 +82,7 @@  #include <linux/module.h>  #include <linux/of_platform.h>  #include <linux/platform_device.h> +#include <linux/pm_runtime.h>  #include <linux/slab.h>  #include <linux/timer.h> @@ -280,6 +281,8 @@  #define ISR_COMPLETE(err)	(ISR_COMPLETE_M | (ISR_STATUS_M & (err)))  #define ISR_FATAL(err)		(ISR_COMPLETE(err) | ISR_FATAL_M) +#define IMG_I2C_PM_TIMEOUT	1000 /* ms */ +  enum img_i2c_mode {  	MODE_INACTIVE,  	MODE_RAW, @@ -408,6 +411,9 @@ struct img_i2c {  	unsigned int raw_timeout;  }; +static int img_i2c_runtime_suspend(struct device *dev); +static int img_i2c_runtime_resume(struct device *dev); +  static void img_i2c_writel(struct img_i2c *i2c, u32 offset, u32 value)  {  	writel(value, i2c->base + offset); @@ -826,9 +832,9 @@ next_atomic_cmd:   * Timer function to check if something has gone wrong in automatic mode (so we   * don't have to handle so many interrupts just to catch an exception).   */ -static void img_i2c_check_timer(unsigned long arg) +static void img_i2c_check_timer(struct timer_list *t)  { -	struct img_i2c *i2c = (struct img_i2c *)arg; +	struct img_i2c *i2c = from_timer(i2c, t, check_timer);  	unsigned long flags;  	unsigned int line_status; @@ -1054,8 +1060,8 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,  			atomic = true;  	} -	ret = clk_prepare_enable(i2c->scb_clk); -	if (ret) +	ret = pm_runtime_get_sync(adap->dev.parent); +	if (ret < 0)  		return ret;  	for (i = 0; i < num; i++) { @@ -1131,7 +1137,8 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,  			break;  	} -	clk_disable_unprepare(i2c->scb_clk); +	pm_runtime_mark_last_busy(adap->dev.parent); +	pm_runtime_put_autosuspend(adap->dev.parent);  	return i2c->msg_status ? i2c->msg_status : num;  } @@ -1149,12 +1156,13 @@ static const struct i2c_algorithm img_i2c_algo = {  static int img_i2c_init(struct img_i2c *i2c)  {  	unsigned int clk_khz, bitrate_khz, clk_period, tckh, tckl, tsdh; -	unsigned int i, ret, data, prescale, inc, int_bitrate, filt; +	unsigned int i, data, prescale, inc, int_bitrate, filt;  	struct img_i2c_timings timing;  	u32 rev; +	int ret; -	ret = clk_prepare_enable(i2c->scb_clk); -	if (ret) +	ret = pm_runtime_get_sync(i2c->adap.dev.parent); +	if (ret < 0)  		return ret;  	rev = img_i2c_readl(i2c, SCB_CORE_REV_REG); @@ -1163,7 +1171,8 @@ static int img_i2c_init(struct img_i2c *i2c)  			 "Unknown hardware revision (%d.%d.%d.%d)\n",  			 (rev >> 24) & 0xff, (rev >> 16) & 0xff,  			 (rev >> 8) & 0xff, rev & 0xff); -		clk_disable_unprepare(i2c->scb_clk); +		pm_runtime_mark_last_busy(i2c->adap.dev.parent); +		pm_runtime_put_autosuspend(i2c->adap.dev.parent);  		return -EINVAL;  	} @@ -1314,7 +1323,8 @@ static int img_i2c_init(struct img_i2c *i2c)  	/* Perform a synchronous sequence to reset the bus */  	ret = img_i2c_reset_bus(i2c); -	clk_disable_unprepare(i2c->scb_clk); +	pm_runtime_mark_last_busy(i2c->adap.dev.parent); +	pm_runtime_put_autosuspend(i2c->adap.dev.parent);  	return ret;  } @@ -1362,8 +1372,7 @@ static int img_i2c_probe(struct platform_device *pdev)  	}  	/* Set up the exception check timer */ -	setup_timer(&i2c->check_timer, img_i2c_check_timer, -		    (unsigned long)i2c); +	timer_setup(&i2c->check_timer, img_i2c_check_timer, 0);  	i2c->bitrate = timings[0].max_bitrate;  	if (!of_property_read_u32(node, "clock-frequency", &val)) @@ -1384,22 +1393,30 @@ static int img_i2c_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, i2c); -	ret = clk_prepare_enable(i2c->sys_clk); -	if (ret) -		return ret; +	pm_runtime_set_autosuspend_delay(&pdev->dev, IMG_I2C_PM_TIMEOUT); +	pm_runtime_use_autosuspend(&pdev->dev); +	pm_runtime_enable(&pdev->dev); +	if (!pm_runtime_enabled(&pdev->dev)) { +		ret = img_i2c_runtime_resume(&pdev->dev); +		if (ret) +			return ret; +	}  	ret = img_i2c_init(i2c);  	if (ret) -		goto disable_clk; +		goto rpm_disable;  	ret = i2c_add_numbered_adapter(&i2c->adap);  	if (ret < 0) -		goto disable_clk; +		goto rpm_disable;  	return 0; -disable_clk: -	clk_disable_unprepare(i2c->sys_clk); +rpm_disable: +	if (!pm_runtime_enabled(&pdev->dev)) +		img_i2c_runtime_suspend(&pdev->dev); +	pm_runtime_disable(&pdev->dev); +	pm_runtime_dont_use_autosuspend(&pdev->dev);  	return ret;  } @@ -1408,19 +1425,55 @@ static int img_i2c_remove(struct platform_device *dev)  	struct img_i2c *i2c = platform_get_drvdata(dev);  	i2c_del_adapter(&i2c->adap); +	pm_runtime_disable(&dev->dev); +	if (!pm_runtime_status_suspended(&dev->dev)) +		img_i2c_runtime_suspend(&dev->dev); + +	return 0; +} + +static int img_i2c_runtime_suspend(struct device *dev) +{ +	struct img_i2c *i2c = dev_get_drvdata(dev); + +	clk_disable_unprepare(i2c->scb_clk);  	clk_disable_unprepare(i2c->sys_clk);  	return 0;  } +static int img_i2c_runtime_resume(struct device *dev) +{ +	struct img_i2c *i2c = dev_get_drvdata(dev); +	int ret; + +	ret = clk_prepare_enable(i2c->sys_clk); +	if (ret) { +		dev_err(dev, "Unable to enable sys clock\n"); +		return ret; +	} + +	ret = clk_prepare_enable(i2c->scb_clk); +	if (ret) { +		dev_err(dev, "Unable to enable scb clock\n"); +		clk_disable_unprepare(i2c->sys_clk); +		return ret; +	} + +	return 0; +} +  #ifdef CONFIG_PM_SLEEP  static int img_i2c_suspend(struct device *dev)  {  	struct img_i2c *i2c = dev_get_drvdata(dev); +	int ret; -	img_i2c_switch_mode(i2c, MODE_SUSPEND); +	ret = pm_runtime_force_suspend(dev); +	if (ret) +		return ret; -	clk_disable_unprepare(i2c->sys_clk); +	img_i2c_switch_mode(i2c, MODE_SUSPEND);  	return 0;  } @@ -1430,7 +1483,7 @@ static int img_i2c_resume(struct device *dev)  	struct img_i2c *i2c = dev_get_drvdata(dev);  	int ret; -	ret = clk_prepare_enable(i2c->sys_clk); +	ret = pm_runtime_force_resume(dev);  	if (ret)  		return ret; @@ -1440,7 +1493,12 @@ static int img_i2c_resume(struct device *dev)  }  #endif /* CONFIG_PM_SLEEP */ -static SIMPLE_DEV_PM_OPS(img_i2c_pm, img_i2c_suspend, img_i2c_resume); +static const struct dev_pm_ops img_i2c_pm = { +	SET_RUNTIME_PM_OPS(img_i2c_runtime_suspend, +			   img_i2c_runtime_resume, +			   NULL) +	SET_SYSTEM_SLEEP_PM_OPS(img_i2c_suspend, img_i2c_resume) +};  static const struct of_device_id img_scb_i2c_match[] = {  	{ .compatible = "img,scb-i2c" }, diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 96caf378b1dc..950a9d74f54d 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -322,7 +322,7 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] = {  static u32 mpc_i2c_get_sec_cfg_8xxx(void)  { -	struct device_node *node = NULL; +	struct device_node *node;  	u32 __iomem *reg;  	u32 val = 0; @@ -700,7 +700,7 @@ static int fsl_i2c_probe(struct platform_device *op)  		}  	} -	if (of_get_property(op->dev.of_node, "fsl,preserve-clocking", NULL)) { +	if (of_property_read_bool(op->dev.of_node, "fsl,preserve-clocking")) {  		clock = MPC_I2C_CLOCK_PRESERVE;  	} else {  		prop = of_get_property(op->dev.of_node, "clock-frequency", diff --git a/drivers/i2c/busses/i2c-octeon-core.h b/drivers/i2c/busses/i2c-octeon-core.h index aa3c8f4771c1..a7ef19855bb8 100644 --- a/drivers/i2c/busses/i2c-octeon-core.h +++ b/drivers/i2c/busses/i2c-octeon-core.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  #include <linux/atomic.h>  #include <linux/clk.h>  #include <linux/delay.h> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 23c2ea2baedc..b9172f08fd05 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -487,6 +487,22 @@ static int omap_i2c_init(struct omap_i2c_dev *omap)  }  /* + * Try bus recovery, but only if SDA is actually low. + */ +static int omap_i2c_recover_bus(struct omap_i2c_dev *omap) +{ +	u16 systest; + +	systest = omap_i2c_read_reg(omap, OMAP_I2C_SYSTEST_REG); +	if ((systest & OMAP_I2C_SYSTEST_SCL_I_FUNC) && +	    (systest & OMAP_I2C_SYSTEST_SDA_I_FUNC)) +		return 0; /* bus seems to already be fine */ +	if (!(systest & OMAP_I2C_SYSTEST_SCL_I_FUNC)) +		return -EBUSY; /* recovery would not fix SCL */ +	return i2c_recover_bus(&omap->adapter); +} + +/*   * Waiting on Bus Busy   */  static int omap_i2c_wait_for_bb(struct omap_i2c_dev *omap) @@ -496,7 +512,7 @@ static int omap_i2c_wait_for_bb(struct omap_i2c_dev *omap)  	timeout = jiffies + OMAP_I2C_TIMEOUT;  	while (omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) {  		if (time_after(jiffies, timeout)) -			return i2c_recover_bus(&omap->adapter); +			return omap_i2c_recover_bus(omap);  		msleep(1);  	} @@ -577,8 +593,13 @@ static int omap_i2c_wait_for_bb_valid(struct omap_i2c_dev *omap)  		}  		if (time_after(jiffies, timeout)) { +			/* +			 * SDA or SCL were low for the entire timeout without +			 * any activity detected. Most likely, a slave is +			 * locking up the bus with no master driving the clock. +			 */  			dev_warn(omap->dev, "timeout waiting for bus ready\n"); -			return -ETIMEDOUT; +			return omap_i2c_recover_bus(omap);  		}  		msleep(1); diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c index faa8fb8f2b8f..fa41ff799533 100644 --- a/drivers/i2c/busses/i2c-parport-light.c +++ b/drivers/i2c/busses/i2c-parport-light.c @@ -123,7 +123,6 @@ static struct i2c_adapter parport_adapter = {  /* SMBus alert support */  static struct i2c_smbus_alert_setup alert_data = { -	.alert_edge_triggered	= 1,  };  static struct i2c_client *ara;  static struct lineop parport_ctrl_irq = { diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c index a8e54df4aed6..319209a07353 100644 --- a/drivers/i2c/busses/i2c-parport.c +++ b/drivers/i2c/busses/i2c-parport.c @@ -237,7 +237,6 @@ static void i2c_parport_attach(struct parport *port)  	/* Setup SMBus alert if supported */  	if (adapter_parm[type].smbus_alert) { -		adapter->alert_data.alert_edge_triggered = 1;  		adapter->ara = i2c_setup_smbus_alert(&adapter->adapter,  						     &adapter->alert_data);  		if (adapter->ara) diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 174579d32e5f..462948e2c535 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -983,7 +983,7 @@ static void piix4_adap_remove(struct i2c_adapter *adap)  	if (adapdata->smba) {  		i2c_del_adapter(adap); -		if (adapdata->port == (0 << 1)) { +		if (adapdata->port == (0 << piix4_port_shift_sb800)) {  			release_region(adapdata->smba, SMBIOSIZE);  			if (adapdata->sb800_main)  				release_region(SB800_PIIX4_SMB_IDX, 2); diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 42d6b3a226f8..a542041df0cd 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -112,7 +112,6 @@ static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)  		jiffies, expires);  	timer->expires = jiffies + expires; -	timer->data = (unsigned long)alg_data;  	add_timer(timer);  } @@ -435,9 +434,9 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)  	return IRQ_HANDLED;  } -static void i2c_pnx_timeout(unsigned long data) +static void i2c_pnx_timeout(struct timer_list *t)  { -	struct i2c_pnx_algo_data *alg_data = (struct i2c_pnx_algo_data *)data; +	struct i2c_pnx_algo_data *alg_data = from_timer(alg_data, t, mif.timer);  	u32 ctl;  	dev_err(&alg_data->adapter.dev, @@ -659,8 +658,7 @@ static int i2c_pnx_probe(struct platform_device *pdev)  	if (IS_ERR(alg_data->clk))  		return PTR_ERR(alg_data->clk); -	setup_timer(&alg_data->mif.timer, i2c_pnx_timeout, -			(unsigned long)alg_data); +	timer_setup(&alg_data->mif.timer, i2c_pnx_timeout, 0);  	snprintf(alg_data->adapter.name, sizeof(alg_data->adapter.name),  		 "%s", pdev->name); diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c index c811af4c8d81..95c2f1ce3cad 100644 --- a/drivers/i2c/busses/i2c-riic.c +++ b/drivers/i2c/busses/i2c-riic.c @@ -84,12 +84,7 @@  #define ICSR2_NACKF	0x10 -/* ICBRx (@ PCLK 33MHz) */  #define ICBR_RESERVED	0xe0 /* Should be 1 on writes */ -#define ICBRL_SP100K	(19 | ICBR_RESERVED) -#define ICBRH_SP100K	(16 | ICBR_RESERVED) -#define ICBRL_SP400K	(21 | ICBR_RESERVED) -#define ICBRH_SP400K	(9 | ICBR_RESERVED)  #define RIIC_INIT_MSG	-1 @@ -288,48 +283,99 @@ static const struct i2c_algorithm riic_algo = {  	.functionality	= riic_func,  }; -static int riic_init_hw(struct riic_dev *riic, u32 spd) +static int riic_init_hw(struct riic_dev *riic, struct i2c_timings *t)  {  	int ret;  	unsigned long rate; +	int total_ticks, cks, brl, brh;  	ret = clk_prepare_enable(riic->clk);  	if (ret)  		return ret; +	if (t->bus_freq_hz > 400000) { +		dev_err(&riic->adapter.dev, +			"unsupported bus speed (%dHz). 400000 max\n", +			t->bus_freq_hz); +		clk_disable_unprepare(riic->clk); +		return -EINVAL; +	} + +	rate = clk_get_rate(riic->clk); +  	/* -	 * TODO: Implement formula to calculate the timing values depending on -	 * variable parent clock rate and arbitrary bus speed +	 * Assume the default register settings: +	 *  FER.SCLE = 1 (SCL sync circuit enabled, adds 2 or 3 cycles) +	 *  FER.NFE = 1 (noise circuit enabled) +	 *  MR3.NF = 0 (1 cycle of noise filtered out) +	 * +	 * Freq (CKS=000) = (I2CCLK + tr + tf)/ (BRH + 3 + 1) + (BRL + 3 + 1) +	 * Freq (CKS!=000) = (I2CCLK + tr + tf)/ (BRH + 2 + 1) + (BRL + 2 + 1)  	 */ -	rate = clk_get_rate(riic->clk); -	if (rate != 33325000) { -		dev_err(&riic->adapter.dev, -			"invalid parent clk (%lu). Must be 33325000Hz\n", rate); + +	/* +	 * Determine reference clock rate. We must be able to get the desired +	 * frequency with only 62 clock ticks max (31 high, 31 low). +	 * Aim for a duty of 60% LOW, 40% HIGH. +	 */ +	total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz); + +	for (cks = 0; cks < 7; cks++) { +		/* +		 * 60% low time must be less than BRL + 2 + 1 +		 * BRL max register value is 0x1F. +		 */ +		brl = ((total_ticks * 6) / 10); +		if (brl <= (0x1F + 3)) +			break; + +		total_ticks /= 2; +		rate /= 2; +	} + +	if (brl > (0x1F + 3)) { +		dev_err(&riic->adapter.dev, "invalid speed (%lu). Too slow.\n", +			(unsigned long)t->bus_freq_hz);  		clk_disable_unprepare(riic->clk);  		return -EINVAL;  	} +	brh = total_ticks - brl; + +	/* Remove automatic clock ticks for sync circuit and NF */ +	if (cks == 0) { +		brl -= 4; +		brh -= 4; +	} else { +		brl -= 3; +		brh -= 3; +	} + +	/* +	 * Remove clock ticks for rise and fall times. Convert ns to clock +	 * ticks. +	 */ +	brl -= t->scl_fall_ns / (1000000000 / rate); +	brh -= t->scl_rise_ns / (1000000000 / rate); + +	/* Adjust for min register values for when SCLE=1 and NFE=1 */ +	if (brl < 1) +		brl = 1; +	if (brh < 1) +		brh = 1; + +	pr_debug("i2c-riic: freq=%lu, duty=%d, fall=%lu, rise=%lu, cks=%d, brl=%d, brh=%d\n", +		 rate / total_ticks, ((brl + 3) * 100) / (brl + brh + 6), +		 t->scl_fall_ns / (1000000000 / rate), +		 t->scl_rise_ns / (1000000000 / rate), cks, brl, brh); +  	/* Changing the order of accessing IICRST and ICE may break things! */  	writeb(ICCR1_IICRST | ICCR1_SOWP, riic->base + RIIC_ICCR1);  	riic_clear_set_bit(riic, 0, ICCR1_ICE, RIIC_ICCR1); -	switch (spd) { -	case 100000: -		writeb(ICMR1_CKS(3), riic->base + RIIC_ICMR1); -		writeb(ICBRH_SP100K, riic->base + RIIC_ICBRH); -		writeb(ICBRL_SP100K, riic->base + RIIC_ICBRL); -		break; -	case 400000: -		writeb(ICMR1_CKS(1), riic->base + RIIC_ICMR1); -		writeb(ICBRH_SP400K, riic->base + RIIC_ICBRH); -		writeb(ICBRL_SP400K, riic->base + RIIC_ICBRL); -		break; -	default: -		dev_err(&riic->adapter.dev, -			"unsupported bus speed (%dHz). Use 100000 or 400000\n", spd); -		clk_disable_unprepare(riic->clk); -		return -EINVAL; -	} +	writeb(ICMR1_CKS(cks), riic->base + RIIC_ICMR1); +	writeb(brh | ICBR_RESERVED, riic->base + RIIC_ICBRH); +	writeb(brl | ICBR_RESERVED, riic->base + RIIC_ICBRL);  	writeb(0, riic->base + RIIC_ICSER);  	writeb(ICMR3_ACKWP | ICMR3_RDRFS, riic->base + RIIC_ICMR3); @@ -351,11 +397,10 @@ static struct riic_irq_desc riic_irqs[] = {  static int riic_i2c_probe(struct platform_device *pdev)  { -	struct device_node *np = pdev->dev.of_node;  	struct riic_dev *riic;  	struct i2c_adapter *adap;  	struct resource *res; -	u32 bus_rate = 0; +	struct i2c_timings i2c_t;  	int i, ret;  	riic = devm_kzalloc(&pdev->dev, sizeof(*riic), GFP_KERNEL); @@ -396,8 +441,9 @@ static int riic_i2c_probe(struct platform_device *pdev)  	init_completion(&riic->msg_done); -	of_property_read_u32(np, "clock-frequency", &bus_rate); -	ret = riic_init_hw(riic, bus_rate); +	i2c_parse_fw_timings(&pdev->dev, &i2c_t, true); + +	ret = riic_init_hw(riic, &i2c_t);  	if (ret)  		return ret; @@ -408,7 +454,8 @@ static int riic_i2c_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, riic); -	dev_info(&pdev->dev, "registered with %dHz bus speed\n", bus_rate); +	dev_info(&pdev->dev, "registered with %dHz bus speed\n", +		 i2c_t.bus_freq_hz);  	return 0;  } diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 6f2aaeb7c4fa..c03acdf71397 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -881,7 +881,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)  	struct sh_mobile_i2c_data *pd;  	struct i2c_adapter *adap;  	struct resource *res; -	const struct of_device_id *match; +	const struct sh_mobile_dt_config *config;  	int ret;  	u32 bus_speed; @@ -913,10 +913,8 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)  	pd->bus_speed = ret ? STANDARD_MODE : bus_speed;  	pd->clks_per_count = 1; -	match = of_match_device(sh_mobile_i2c_dt_ids, &dev->dev); -	if (match) { -		const struct sh_mobile_dt_config *config = match->data; - +	config = of_device_get_match_data(&dev->dev); +	if (config) {  		pd->clks_per_count = config->clks_per_count;  		if (config->setup) diff --git a/drivers/i2c/busses/i2c-stm32.h b/drivers/i2c/busses/i2c-stm32.h index dab51761f8c5..d4f9cef251ac 100644 --- a/drivers/i2c/busses/i2c-stm32.h +++ b/drivers/i2c/busses/i2c-stm32.h @@ -1,10 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * i2c-stm32.h   *   * Copyright (C) M'boumba Cedric Madianga 2017 + * Copyright (C) STMicroelectronics 2017   * Author: M'boumba Cedric Madianga <[email protected]>   * - * License terms:  GNU General Public License (GPL), version 2   */  #ifndef _I2C_STM32_H diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c index 4ec108496f15..47c8d00de53f 100644 --- a/drivers/i2c/busses/i2c-stm32f4.c +++ b/drivers/i2c/busses/i2c-stm32f4.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * Driver for STMicroelectronics STM32 I2C controller   * @@ -6,11 +7,11 @@   * http://www.st.com/resource/en/reference_manual/DM00031020.pdf   *   * Copyright (C) M'boumba Cedric Madianga 2016 + * Copyright (C) STMicroelectronics 2017   * Author: M'boumba Cedric Madianga <[email protected]>   *   * This driver is based on i2c-st.c   * - * License terms:  GNU General Public License (GPL), version 2   */  #include <linux/clk.h> diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index d4a6e9c2e9aa..b445b3bb0bb1 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * Driver for STMicroelectronics STM32F7 I2C controller   * @@ -7,11 +8,11 @@   * http://www.st.com/resource/en/reference_manual/dm00124865.pdf   *   * Copyright (C) M'boumba Cedric Madianga 2017 + * Copyright (C) STMicroelectronics 2017   * Author: M'boumba Cedric Madianga <[email protected]>   *   * This driver is based on i2c-stm32f4.c   * - * License terms:  GNU General Public License (GPL), version 2   */  #include <linux/clk.h>  #include <linux/delay.h> diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c index addd90a8cb59..7c7fc01116a1 100644 --- a/drivers/i2c/busses/i2c-taos-evm.c +++ b/drivers/i2c/busses/i2c-taos-evm.c @@ -282,8 +282,7 @@ static void taos_disconnect(struct serio *serio)  {  	struct taos_data *taos = serio_get_drvdata(serio); -	if (taos->client) -		i2c_unregister_device(taos->client); +	i2c_unregister_device(taos->client);  	i2c_del_adapter(&taos->adapter);  	serio_close(serio);  	kfree(taos); diff --git a/drivers/i2c/busses/i2c-thunderx-pcidrv.c b/drivers/i2c/busses/i2c-thunderx-pcidrv.c index df0976f4432a..19f8eec38717 100644 --- a/drivers/i2c/busses/i2c-thunderx-pcidrv.c +++ b/drivers/i2c/busses/i2c-thunderx-pcidrv.c @@ -118,8 +118,6 @@ static void thunder_i2c_clock_disable(struct device *dev, struct clk *clk)  static int thunder_i2c_smbus_setup_of(struct octeon_i2c *i2c,  				      struct device_node *node)  { -	u32 type; -  	if (!node)  		return -EINVAL; @@ -127,10 +125,6 @@ static int thunder_i2c_smbus_setup_of(struct octeon_i2c *i2c,  	if (!i2c->alert_data.irq)  		return -EINVAL; -	type = irqd_get_trigger_type(irq_get_irq_data(i2c->alert_data.irq)); -	i2c->alert_data.alert_edge_triggered = -		(type & IRQ_TYPE_LEVEL_MASK) ? 1 : 0; -  	i2c->ara = i2c_setup_smbus_alert(&i2c->adap, &i2c->alert_data);  	if (!i2c->ara)  		return -ENODEV; @@ -149,8 +143,7 @@ static int thunder_i2c_smbus_setup(struct octeon_i2c *i2c,  static void thunder_i2c_smbus_remove(struct octeon_i2c *i2c)  { -	if (i2c->ara) -		i2c_unregister_device(i2c->ara); +	i2c_unregister_device(i2c->ara);  }  static int thunder_i2c_probe_pci(struct pci_dev *pdev, diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c index 7e89ba6fcf6f..a7ac746018ad 100644 --- a/drivers/i2c/busses/i2c-xgene-slimpro.c +++ b/drivers/i2c/busses/i2c-xgene-slimpro.c @@ -129,6 +129,11 @@ struct slimpro_i2c_dev {  #define to_slimpro_i2c_dev(cl)	\  		container_of(cl, struct slimpro_i2c_dev, mbox_client) +enum slimpro_i2c_version { +	XGENE_SLIMPRO_I2C_V1 = 0, +	XGENE_SLIMPRO_I2C_V2 = 1, +}; +  /*   * This function tests and clears a bitmask then returns its old value   */ @@ -476,6 +481,15 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)  		}  	} else {  		struct acpi_pcct_hw_reduced *cppc_ss; +		const struct acpi_device_id *acpi_id; +		int version = XGENE_SLIMPRO_I2C_V1; + +		acpi_id = acpi_match_device(pdev->dev.driver->acpi_match_table, +					    &pdev->dev); +		if (!acpi_id) +			return -EINVAL; + +		version = (int)acpi_id->driver_data;  		if (device_property_read_u32(&pdev->dev, "pcc-channel",  					     &ctx->mbox_idx)) @@ -514,9 +528,16 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)  		 */  		ctx->comm_base_addr = cppc_ss->base_address;  		if (ctx->comm_base_addr) { -			ctx->pcc_comm_addr = memremap(ctx->comm_base_addr, -						      cppc_ss->length, -						      MEMREMAP_WB); +			if (version == XGENE_SLIMPRO_I2C_V2) +				ctx->pcc_comm_addr = memremap( +							ctx->comm_base_addr, +							cppc_ss->length, +							MEMREMAP_WT); +			else +				ctx->pcc_comm_addr = memremap( +							ctx->comm_base_addr, +							cppc_ss->length, +							MEMREMAP_WB);  		} else {  			dev_err(&pdev->dev, "Failed to get PCC comm region\n");  			rc = -ENOENT; @@ -581,7 +602,8 @@ MODULE_DEVICE_TABLE(of, xgene_slimpro_i2c_dt_ids);  #ifdef CONFIG_ACPI  static const struct acpi_device_id xgene_slimpro_i2c_acpi_ids[] = { -	{"APMC0D40", 0}, +	{"APMC0D40", XGENE_SLIMPRO_I2C_V1}, +	{"APMC0D8B", XGENE_SLIMPRO_I2C_V2},  	{}  };  MODULE_DEVICE_TABLE(acpi, xgene_slimpro_i2c_acpi_ids); diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c index 6b106e94bc09..b970bf8f38e5 100644 --- a/drivers/i2c/busses/i2c-xlp9xx.c +++ b/drivers/i2c/busses/i2c-xlp9xx.c @@ -7,6 +7,7 @@   */  #include <linux/acpi.h> +#include <linux/clk.h>  #include <linux/completion.h>  #include <linux/i2c.h>  #include <linux/init.h> @@ -81,9 +82,12 @@ struct xlp9xx_i2c_dev {  	struct completion msg_complete;  	int irq;  	bool msg_read; +	bool len_recv; +	bool client_pec;  	u32 __iomem *base;  	u32 msg_buf_remaining;  	u32 msg_len; +	u32 ip_clk_hz;  	u32 clk_hz;  	u32 msg_err;  	u8 *msg_buf; @@ -141,10 +145,25 @@ static void xlp9xx_i2c_fill_tx_fifo(struct xlp9xx_i2c_dev *priv)  static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)  {  	u32 len, i; -	u8 *buf = priv->msg_buf; +	u8 rlen, *buf = priv->msg_buf;  	len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) &  				  XLP9XX_I2C_FIFO_WCNT_MASK; +	if (!len) +		return; +	if (priv->len_recv) { +		/* read length byte */ +		rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); +		*buf++ = rlen; +		len--; +		if (priv->client_pec) +			++rlen; +		/* update remaining bytes and message length */ +		priv->msg_buf_remaining = rlen; +		priv->msg_len = rlen + 1; +		priv->len_recv = false; +	} +  	len = min(priv->msg_buf_remaining, len);  	for (i = 0; i < len; i++, buf++)  		*buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); @@ -213,7 +232,7 @@ static int xlp9xx_i2c_init(struct xlp9xx_i2c_dev *priv)  	 * The controller uses 5 * SCL clock internally.  	 * So prescale value should be divided by 5.  	 */ -	prescale = DIV_ROUND_UP(XLP9XX_I2C_IP_CLK_FREQ, priv->clk_hz); +	prescale = DIV_ROUND_UP(priv->ip_clk_hz, priv->clk_hz);  	prescale = ((prescale - 8) / 5) - 1;  	xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, XLP9XX_I2C_CTRL_RST);  	xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, XLP9XX_I2C_CTRL_EN | @@ -228,7 +247,7 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,  			       int last_msg)  {  	unsigned long timeleft; -	u32 intr_mask, cmd, val; +	u32 intr_mask, cmd, val, len;  	priv->msg_buf = msg->buf;  	priv->msg_buf_remaining = priv->msg_len = msg->len; @@ -261,9 +280,13 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,  	else  		val &= ~XLP9XX_I2C_CTRL_ADDMODE; +	priv->len_recv = msg->flags & I2C_M_RECV_LEN; +	len = priv->len_recv ? XLP9XX_I2C_FIFO_SIZE : msg->len; +	priv->client_pec = msg->flags & I2C_CLIENT_PEC; +  	/* set data length to be transferred */  	val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) | -	      (msg->len << XLP9XX_I2C_CTRL_MCTLEN_SHIFT); +	      (len << XLP9XX_I2C_CTRL_MCTLEN_SHIFT);  	xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, val);  	/* fill fifo during tx */ @@ -310,6 +333,9 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,  		return -ETIMEDOUT;  	} +	/* update msg->len with actual received length */ +	if (msg->flags & I2C_M_RECV_LEN) +		msg->len = priv->msg_len;  	return 0;  } @@ -342,9 +368,19 @@ static const struct i2c_algorithm xlp9xx_i2c_algo = {  static int xlp9xx_i2c_get_frequency(struct platform_device *pdev,  				    struct xlp9xx_i2c_dev *priv)  { +	struct clk *clk;  	u32 freq;  	int err; +	clk = devm_clk_get(&pdev->dev, NULL); +	if (IS_ERR(clk)) { +		priv->ip_clk_hz = XLP9XX_I2C_IP_CLK_FREQ; +		dev_dbg(&pdev->dev, "using default input frequency %u\n", +			priv->ip_clk_hz); +	} else { +		priv->ip_clk_hz = clk_get_rate(clk); +	} +  	err = device_property_read_u32(&pdev->dev, "clock-frequency", &freq);  	if (err) {  		freq = XLP9XX_I2C_DEFAULT_FREQ; diff --git a/drivers/i2c/i2c-boardinfo.c b/drivers/i2c/i2c-boardinfo.c index 31186ead5a40..509a6007cdf6 100644 --- a/drivers/i2c/i2c-boardinfo.c +++ b/drivers/i2c/i2c-boardinfo.c @@ -86,6 +86,7 @@ int i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsig  					property_entries_dup(info->properties);  			if (IS_ERR(devinfo->board_info.properties)) {  				status = PTR_ERR(devinfo->board_info.properties); +				kfree(devinfo);  				break;  			}  		} @@ -98,6 +99,7 @@ int i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsig  					GFP_KERNEL);  			if (!devinfo->board_info.resources) {  				status = -ENOMEM; +				kfree(devinfo);  				break;  			}  		} diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 56e46581b84b..706164b4c5be 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -29,6 +29,7 @@  #include <linux/errno.h>  #include <linux/gpio.h>  #include <linux/i2c.h> +#include <linux/i2c-smbus.h>  #include <linux/idr.h>  #include <linux/init.h>  #include <linux/irqflags.h> @@ -205,9 +206,6 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)  	 */  	while (i++ < RECOVERY_CLK_CNT * 2) {  		if (val) { -			/* Break if SDA is high */ -			if (bri->get_sda && bri->get_sda(adap)) -					break;  			/* SCL shouldn't be low here */  			if (!bri->get_scl(adap)) {  				dev_err(&adap->dev, @@ -215,6 +213,9 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)  				ret = -EBUSY;  				break;  			} +			/* Break if SDA is high */ +			if (bri->get_sda && bri->get_sda(adap)) +				break;  		}  		val = !val; @@ -222,6 +223,10 @@ static int i2c_generic_recovery(struct i2c_adapter *adap)  		ndelay(RECOVERY_NDELAY);  	} +	/* check if recovery actually succeeded */ +	if (bri->get_sda && !bri->get_sda(adap)) +		ret = -EBUSY; +  	if (bri->unprepare_recovery)  		bri->unprepare_recovery(adap); @@ -666,10 +671,16 @@ static void i2c_adapter_unlock_bus(struct i2c_adapter *adapter,  }  static void i2c_dev_set_name(struct i2c_adapter *adap, -			     struct i2c_client *client) +			     struct i2c_client *client, +			     struct i2c_board_info const *info)  {  	struct acpi_device *adev = ACPI_COMPANION(&client->dev); +	if (info && info->dev_name) { +		dev_set_name(&client->dev, "i2c-%s", info->dev_name); +		return; +	} +  	if (adev) {  		dev_set_name(&client->dev, "i2c-%s", acpi_dev_name(adev));  		return; @@ -766,7 +777,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)  	client->dev.of_node = info->of_node;  	client->dev.fwnode = info->fwnode; -	i2c_dev_set_name(adap, client); +	i2c_dev_set_name(adap, client, info);  	if (info->properties) {  		status = device_add_properties(&client->dev, info->properties); @@ -808,6 +819,8 @@ EXPORT_SYMBOL_GPL(i2c_new_device);   */  void i2c_unregister_device(struct i2c_client *client)  { +	if (!client) +		return;  	if (client->dev.of_node)  		of_node_clear_flag(client->dev.of_node, OF_POPULATED);  	if (ACPI_COMPANION(&client->dev)) @@ -1259,6 +1272,10 @@ static int i2c_register_adapter(struct i2c_adapter *adap)  		goto out_list;  	} +	res = of_i2c_setup_smbus_alert(adap); +	if (res) +		goto out_reg; +  	dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);  	pm_runtime_no_callbacks(&adap->dev); @@ -1290,6 +1307,10 @@ static int i2c_register_adapter(struct i2c_adapter *adap)  	return 0; +out_reg: +	init_completion(&adap->dev_released); +	device_unregister(&adap->dev); +	wait_for_completion(&adap->dev_released);  out_list:  	mutex_lock(&core_lock);  	idr_remove(&i2c_adapter_idr, adap->nr); @@ -1417,8 +1438,7 @@ static int __unregister_client(struct device *dev, void *dummy)  static int __unregister_dummy(struct device *dev, void *dummy)  {  	struct i2c_client *client = i2c_verify_client(dev); -	if (client) -		i2c_unregister_device(client); +	i2c_unregister_device(client);  	return 0;  } diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c index 10f00a82ec9d..4bb9927afd01 100644 --- a/drivers/i2c/i2c-core-smbus.c +++ b/drivers/i2c/i2c-core-smbus.c @@ -17,6 +17,7 @@  #include <linux/device.h>  #include <linux/err.h>  #include <linux/i2c.h> +#include <linux/i2c-smbus.h>  #define CREATE_TRACE_POINTS  #include <trace/events/smbus.h> @@ -592,3 +593,57 @@ s32 i2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client,  	return i;  }  EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data_or_emulated); + +/** + * i2c_setup_smbus_alert - Setup SMBus alert support + * @adapter: the target adapter + * @setup: setup data for the SMBus alert handler + * Context: can sleep + * + * Setup handling of the SMBus alert protocol on a given I2C bus segment. + * + * Handling can be done either through our IRQ handler, or by the + * adapter (from its handler, periodic polling, or whatever). + * + * NOTE that if we manage the IRQ, we *MUST* know if it's level or + * edge triggered in order to hand it to the workqueue correctly. + * If triggering the alert seems to wedge the system, you probably + * should have said it's level triggered. + * + * This returns the ara client, which should be saved for later use with + * i2c_handle_smbus_alert() and ultimately i2c_unregister_device(); or NULL + * to indicate an error. + */ +struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter, +					 struct i2c_smbus_alert_setup *setup) +{ +	struct i2c_board_info ara_board_info = { +		I2C_BOARD_INFO("smbus_alert", 0x0c), +		.platform_data = setup, +	}; + +	return i2c_new_device(adapter, &ara_board_info); +} +EXPORT_SYMBOL_GPL(i2c_setup_smbus_alert); + +#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF) +int of_i2c_setup_smbus_alert(struct i2c_adapter *adapter) +{ +	struct i2c_client *client; +	int irq; + +	irq = of_property_match_string(adapter->dev.of_node, "interrupt-names", +				       "smbus_alert"); +	if (irq == -EINVAL || irq == -ENODATA) +		return 0; +	else if (irq < 0) +		return irq; + +	client = i2c_setup_smbus_alert(adapter, NULL); +	if (!client) +		return -ENODEV; + +	return 0; +} +EXPORT_SYMBOL_GPL(of_i2c_setup_smbus_alert); +#endif diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 6f638bbc922d..2cab27a68479 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -35,6 +35,7 @@  #include <linux/notifier.h>  #include <linux/slab.h>  #include <linux/uaccess.h> +#include <linux/compat.h>  /*   * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a @@ -238,46 +239,29 @@ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)  }  static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, -		unsigned long arg) +		unsigned nmsgs, struct i2c_msg *msgs)  { -	struct i2c_rdwr_ioctl_data rdwr_arg; -	struct i2c_msg *rdwr_pa;  	u8 __user **data_ptrs;  	int i, res; -	if (copy_from_user(&rdwr_arg, -			   (struct i2c_rdwr_ioctl_data __user *)arg, -			   sizeof(rdwr_arg))) -		return -EFAULT; - -	/* Put an arbitrary limit on the number of messages that can -	 * be sent at once */ -	if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) -		return -EINVAL; - -	rdwr_pa = memdup_user(rdwr_arg.msgs, -			      rdwr_arg.nmsgs * sizeof(struct i2c_msg)); -	if (IS_ERR(rdwr_pa)) -		return PTR_ERR(rdwr_pa); - -	data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL); +	data_ptrs = kmalloc(nmsgs * sizeof(u8 __user *), GFP_KERNEL);  	if (data_ptrs == NULL) { -		kfree(rdwr_pa); +		kfree(msgs);  		return -ENOMEM;  	}  	res = 0; -	for (i = 0; i < rdwr_arg.nmsgs; i++) { +	for (i = 0; i < nmsgs; i++) {  		/* Limit the size of the message to a sane amount */ -		if (rdwr_pa[i].len > 8192) { +		if (msgs[i].len > 8192) {  			res = -EINVAL;  			break;  		} -		data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; -		rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len); -		if (IS_ERR(rdwr_pa[i].buf)) { -			res = PTR_ERR(rdwr_pa[i].buf); +		data_ptrs[i] = (u8 __user *)msgs[i].buf; +		msgs[i].buf = memdup_user(data_ptrs[i], msgs[i].len); +		if (IS_ERR(msgs[i].buf)) { +			res = PTR_ERR(msgs[i].buf);  			break;  		} @@ -292,121 +276,117 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,  		 * greater (for example to account for a checksum byte at  		 * the end of the message.)  		 */ -		if (rdwr_pa[i].flags & I2C_M_RECV_LEN) { -			if (!(rdwr_pa[i].flags & I2C_M_RD) || -			    rdwr_pa[i].buf[0] < 1 || -			    rdwr_pa[i].len < rdwr_pa[i].buf[0] + +		if (msgs[i].flags & I2C_M_RECV_LEN) { +			if (!(msgs[i].flags & I2C_M_RD) || +			    msgs[i].buf[0] < 1 || +			    msgs[i].len < msgs[i].buf[0] +  					     I2C_SMBUS_BLOCK_MAX) {  				res = -EINVAL;  				break;  			} -			rdwr_pa[i].len = rdwr_pa[i].buf[0]; +			msgs[i].len = msgs[i].buf[0];  		}  	}  	if (res < 0) {  		int j;  		for (j = 0; j < i; ++j) -			kfree(rdwr_pa[j].buf); +			kfree(msgs[j].buf);  		kfree(data_ptrs); -		kfree(rdwr_pa); +		kfree(msgs);  		return res;  	} -	res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs); +	res = i2c_transfer(client->adapter, msgs, nmsgs);  	while (i-- > 0) { -		if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD)) { -			if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf, -					 rdwr_pa[i].len)) +		if (res >= 0 && (msgs[i].flags & I2C_M_RD)) { +			if (copy_to_user(data_ptrs[i], msgs[i].buf, +					 msgs[i].len))  				res = -EFAULT;  		} -		kfree(rdwr_pa[i].buf); +		kfree(msgs[i].buf);  	}  	kfree(data_ptrs); -	kfree(rdwr_pa); +	kfree(msgs);  	return res;  }  static noinline int i2cdev_ioctl_smbus(struct i2c_client *client, -		unsigned long arg) +		u8 read_write, u8 command, u32 size, +		union i2c_smbus_data __user *data)  { -	struct i2c_smbus_ioctl_data data_arg;  	union i2c_smbus_data temp = {};  	int datasize, res; -	if (copy_from_user(&data_arg, -			   (struct i2c_smbus_ioctl_data __user *) arg, -			   sizeof(struct i2c_smbus_ioctl_data))) -		return -EFAULT; -	if ((data_arg.size != I2C_SMBUS_BYTE) && -	    (data_arg.size != I2C_SMBUS_QUICK) && -	    (data_arg.size != I2C_SMBUS_BYTE_DATA) && -	    (data_arg.size != I2C_SMBUS_WORD_DATA) && -	    (data_arg.size != I2C_SMBUS_PROC_CALL) && -	    (data_arg.size != I2C_SMBUS_BLOCK_DATA) && -	    (data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) && -	    (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) && -	    (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) { +	if ((size != I2C_SMBUS_BYTE) && +	    (size != I2C_SMBUS_QUICK) && +	    (size != I2C_SMBUS_BYTE_DATA) && +	    (size != I2C_SMBUS_WORD_DATA) && +	    (size != I2C_SMBUS_PROC_CALL) && +	    (size != I2C_SMBUS_BLOCK_DATA) && +	    (size != I2C_SMBUS_I2C_BLOCK_BROKEN) && +	    (size != I2C_SMBUS_I2C_BLOCK_DATA) && +	    (size != I2C_SMBUS_BLOCK_PROC_CALL)) {  		dev_dbg(&client->adapter->dev,  			"size out of range (%x) in ioctl I2C_SMBUS.\n", -			data_arg.size); +			size);  		return -EINVAL;  	}  	/* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,  	   so the check is valid if size==I2C_SMBUS_QUICK too. */ -	if ((data_arg.read_write != I2C_SMBUS_READ) && -	    (data_arg.read_write != I2C_SMBUS_WRITE)) { +	if ((read_write != I2C_SMBUS_READ) && +	    (read_write != I2C_SMBUS_WRITE)) {  		dev_dbg(&client->adapter->dev,  			"read_write out of range (%x) in ioctl I2C_SMBUS.\n", -			data_arg.read_write); +			read_write);  		return -EINVAL;  	}  	/* Note that command values are always valid! */ -	if ((data_arg.size == I2C_SMBUS_QUICK) || -	    ((data_arg.size == I2C_SMBUS_BYTE) && -	    (data_arg.read_write == I2C_SMBUS_WRITE))) +	if ((size == I2C_SMBUS_QUICK) || +	    ((size == I2C_SMBUS_BYTE) && +	    (read_write == I2C_SMBUS_WRITE)))  		/* These are special: we do not use data */  		return i2c_smbus_xfer(client->adapter, client->addr, -				      client->flags, data_arg.read_write, -				      data_arg.command, data_arg.size, NULL); +				      client->flags, read_write, +				      command, size, NULL); -	if (data_arg.data == NULL) { +	if (data == NULL) {  		dev_dbg(&client->adapter->dev,  			"data is NULL pointer in ioctl I2C_SMBUS.\n");  		return -EINVAL;  	} -	if ((data_arg.size == I2C_SMBUS_BYTE_DATA) || -	    (data_arg.size == I2C_SMBUS_BYTE)) -		datasize = sizeof(data_arg.data->byte); -	else if ((data_arg.size == I2C_SMBUS_WORD_DATA) || -		 (data_arg.size == I2C_SMBUS_PROC_CALL)) -		datasize = sizeof(data_arg.data->word); +	if ((size == I2C_SMBUS_BYTE_DATA) || +	    (size == I2C_SMBUS_BYTE)) +		datasize = sizeof(data->byte); +	else if ((size == I2C_SMBUS_WORD_DATA) || +		 (size == I2C_SMBUS_PROC_CALL)) +		datasize = sizeof(data->word);  	else /* size == smbus block, i2c block, or block proc. call */ -		datasize = sizeof(data_arg.data->block); +		datasize = sizeof(data->block); -	if ((data_arg.size == I2C_SMBUS_PROC_CALL) || -	    (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || -	    (data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) || -	    (data_arg.read_write == I2C_SMBUS_WRITE)) { -		if (copy_from_user(&temp, data_arg.data, datasize)) +	if ((size == I2C_SMBUS_PROC_CALL) || +	    (size == I2C_SMBUS_BLOCK_PROC_CALL) || +	    (size == I2C_SMBUS_I2C_BLOCK_DATA) || +	    (read_write == I2C_SMBUS_WRITE)) { +		if (copy_from_user(&temp, data, datasize))  			return -EFAULT;  	} -	if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) { +	if (size == I2C_SMBUS_I2C_BLOCK_BROKEN) {  		/* Convert old I2C block commands to the new  		   convention. This preserves binary compatibility. */ -		data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA; -		if (data_arg.read_write == I2C_SMBUS_READ) +		size = I2C_SMBUS_I2C_BLOCK_DATA; +		if (read_write == I2C_SMBUS_READ)  			temp.block[0] = I2C_SMBUS_BLOCK_MAX;  	}  	res = i2c_smbus_xfer(client->adapter, client->addr, client->flags, -	      data_arg.read_write, data_arg.command, data_arg.size, &temp); -	if (!res && ((data_arg.size == I2C_SMBUS_PROC_CALL) || -		     (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || -		     (data_arg.read_write == I2C_SMBUS_READ))) { -		if (copy_to_user(data_arg.data, &temp, datasize)) +	      read_write, command, size, &temp); +	if (!res && ((size == I2C_SMBUS_PROC_CALL) || +		     (size == I2C_SMBUS_BLOCK_PROC_CALL) || +		     (read_write == I2C_SMBUS_READ))) { +		if (copy_to_user(data, &temp, datasize))  			return -EFAULT;  	}  	return res; @@ -454,12 +434,39 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)  		funcs = i2c_get_functionality(client->adapter);  		return put_user(funcs, (unsigned long __user *)arg); -	case I2C_RDWR: -		return i2cdev_ioctl_rdwr(client, arg); +	case I2C_RDWR: { +		struct i2c_rdwr_ioctl_data rdwr_arg; +		struct i2c_msg *rdwr_pa; + +		if (copy_from_user(&rdwr_arg, +				   (struct i2c_rdwr_ioctl_data __user *)arg, +				   sizeof(rdwr_arg))) +			return -EFAULT; + +		/* Put an arbitrary limit on the number of messages that can +		 * be sent at once */ +		if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) +			return -EINVAL; -	case I2C_SMBUS: -		return i2cdev_ioctl_smbus(client, arg); +		rdwr_pa = memdup_user(rdwr_arg.msgs, +				      rdwr_arg.nmsgs * sizeof(struct i2c_msg)); +		if (IS_ERR(rdwr_pa)) +			return PTR_ERR(rdwr_pa); + +		return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa); +	} +	case I2C_SMBUS: { +		struct i2c_smbus_ioctl_data data_arg; +		if (copy_from_user(&data_arg, +				   (struct i2c_smbus_ioctl_data __user *) arg, +				   sizeof(struct i2c_smbus_ioctl_data))) +			return -EFAULT; +		return i2cdev_ioctl_smbus(client, data_arg.read_write, +					  data_arg.command, +					  data_arg.size, +					  data_arg.data); +	}  	case I2C_RETRIES:  		client->adapter->retries = arg;  		break; @@ -480,6 +487,90 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)  	return 0;  } +#ifdef CONFIG_COMPAT + +struct i2c_smbus_ioctl_data32 { +	u8 read_write; +	u8 command; +	u32 size; +	compat_caddr_t data; /* union i2c_smbus_data *data */ +}; + +struct i2c_msg32 { +	u16 addr; +	u16 flags; +	u16 len; +	compat_caddr_t buf; +}; + +struct i2c_rdwr_ioctl_data32 { +	compat_caddr_t msgs; /* struct i2c_msg __user *msgs */ +	u32 nmsgs; +}; + +static long compat_i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ +	struct i2c_client *client = file->private_data; +	unsigned long funcs; +	switch (cmd) { +	case I2C_FUNCS: +		funcs = i2c_get_functionality(client->adapter); +		return put_user(funcs, (compat_ulong_t __user *)arg); +	case I2C_RDWR: { +		struct i2c_rdwr_ioctl_data32 rdwr_arg; +		struct i2c_msg32 *p; +		struct i2c_msg *rdwr_pa; +		int i; + +		if (copy_from_user(&rdwr_arg, +				   (struct i2c_rdwr_ioctl_data32 __user *)arg, +				   sizeof(rdwr_arg))) +			return -EFAULT; + +		if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) +			return -EINVAL; + +		rdwr_pa = kmalloc_array(rdwr_arg.nmsgs, sizeof(struct i2c_msg), +				      GFP_KERNEL); +		if (!rdwr_pa) +			return -ENOMEM; + +		p = compat_ptr(rdwr_arg.msgs); +		for (i = 0; i < rdwr_arg.nmsgs; i++) { +			struct i2c_msg32 umsg; +			if (copy_from_user(&umsg, p + i, sizeof(umsg))) { +				kfree(rdwr_pa); +				return -EFAULT; +			} +			rdwr_pa[i] = (struct i2c_msg) { +				.addr = umsg.addr, +				.flags = umsg.flags, +				.len = umsg.len, +				.buf = compat_ptr(umsg.buf) +			}; +		} + +		return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa); +	} +	case I2C_SMBUS: { +		struct i2c_smbus_ioctl_data32	data32; +		if (copy_from_user(&data32, +				   (void __user *) arg, +				   sizeof(data32))) +			return -EFAULT; +		return i2cdev_ioctl_smbus(client, data32.read_write, +					  data32.command, +					  data32.size, +					  compat_ptr(data32.data)); +	} +	default: +		return i2cdev_ioctl(file, cmd, arg); +	} +} +#else +#define compat_i2cdev_ioctl NULL +#endif +  static int i2cdev_open(struct inode *inode, struct file *file)  {  	unsigned int minor = iminor(inode); @@ -527,6 +618,7 @@ static const struct file_operations i2cdev_fops = {  	.read		= i2cdev_read,  	.write		= i2cdev_write,  	.unlocked_ioctl	= i2cdev_ioctl, +	.compat_ioctl	= compat_i2cdev_ioctl,  	.open		= i2cdev_open,  	.release	= i2cdev_release,  }; diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index f9271c713d20..5a1dd7f13bac 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -21,12 +21,11 @@  #include <linux/interrupt.h>  #include <linux/kernel.h>  #include <linux/module.h> +#include <linux/of_irq.h>  #include <linux/slab.h>  #include <linux/workqueue.h>  struct i2c_smbus_alert { -	unsigned int		alert_edge_triggered:1; -	int			irq;  	struct work_struct	alert;  	struct i2c_client	*ara;		/* Alert response address */  }; @@ -72,13 +71,12 @@ static int smbus_do_alert(struct device *dev, void *addrp)   * The alert IRQ handler needs to hand work off to a task which can issue   * SMBus calls, because those sleeping calls can't be made in IRQ context.   */ -static void smbus_alert(struct work_struct *work) +static irqreturn_t smbus_alert(int irq, void *d)  { -	struct i2c_smbus_alert *alert; +	struct i2c_smbus_alert *alert = d;  	struct i2c_client *ara;  	unsigned short prev_addr = 0;	/* Not a valid address */ -	alert = container_of(work, struct i2c_smbus_alert, alert);  	ara = alert->ara;  	for (;;) { @@ -115,21 +113,17 @@ static void smbus_alert(struct work_struct *work)  		prev_addr = data.addr;  	} -	/* We handled all alerts; re-enable level-triggered IRQs */ -	if (!alert->alert_edge_triggered) -		enable_irq(alert->irq); +	return IRQ_HANDLED;  } -static irqreturn_t smbalert_irq(int irq, void *d) +static void smbalert_work(struct work_struct *work)  { -	struct i2c_smbus_alert *alert = d; +	struct i2c_smbus_alert *alert; -	/* Disable level-triggered IRQs until we handle them */ -	if (!alert->alert_edge_triggered) -		disable_irq_nosync(irq); +	alert = container_of(work, struct i2c_smbus_alert, alert); + +	smbus_alert(0, alert); -	schedule_work(&alert->alert); -	return IRQ_HANDLED;  }  /* Setup SMBALERT# infrastructure */ @@ -139,28 +133,35 @@ static int smbalert_probe(struct i2c_client *ara,  	struct i2c_smbus_alert_setup *setup = dev_get_platdata(&ara->dev);  	struct i2c_smbus_alert *alert;  	struct i2c_adapter *adapter = ara->adapter; -	int res; +	int res, irq;  	alert = devm_kzalloc(&ara->dev, sizeof(struct i2c_smbus_alert),  			     GFP_KERNEL);  	if (!alert)  		return -ENOMEM; -	alert->alert_edge_triggered = setup->alert_edge_triggered; -	alert->irq = setup->irq; -	INIT_WORK(&alert->alert, smbus_alert); +	if (setup) { +		irq = setup->irq; +	} else { +		irq = of_irq_get_byname(adapter->dev.of_node, "smbus_alert"); +		if (irq <= 0) +			return irq; +	} + +	INIT_WORK(&alert->alert, smbalert_work);  	alert->ara = ara; -	if (setup->irq > 0) { -		res = devm_request_irq(&ara->dev, setup->irq, smbalert_irq, -				       0, "smbus_alert", alert); +	if (irq > 0) { +		res = devm_request_threaded_irq(&ara->dev, irq, +						NULL, smbus_alert, +						IRQF_SHARED | IRQF_ONESHOT, +						"smbus_alert", alert);  		if (res)  			return res;  	}  	i2c_set_clientdata(ara, alert); -	dev_info(&adapter->dev, "supports SMBALERT#, %s trigger\n", -		 setup->alert_edge_triggered ? "edge" : "level"); +	dev_info(&adapter->dev, "supports SMBALERT#\n");  	return 0;  } @@ -190,38 +191,6 @@ static struct i2c_driver smbalert_driver = {  };  /** - * i2c_setup_smbus_alert - Setup SMBus alert support - * @adapter: the target adapter - * @setup: setup data for the SMBus alert handler - * Context: can sleep - * - * Setup handling of the SMBus alert protocol on a given I2C bus segment. - * - * Handling can be done either through our IRQ handler, or by the - * adapter (from its handler, periodic polling, or whatever). - * - * NOTE that if we manage the IRQ, we *MUST* know if it's level or - * edge triggered in order to hand it to the workqueue correctly. - * If triggering the alert seems to wedge the system, you probably - * should have said it's level triggered. - * - * This returns the ara client, which should be saved for later use with - * i2c_handle_smbus_alert() and ultimately i2c_unregister_device(); or NULL - * to indicate an error. - */ -struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter, -					 struct i2c_smbus_alert_setup *setup) -{ -	struct i2c_board_info ara_board_info = { -		I2C_BOARD_INFO("smbus_alert", 0x0c), -		.platform_data = setup, -	}; - -	return i2c_new_device(adapter, &ara_board_info); -} -EXPORT_SYMBOL_GPL(i2c_setup_smbus_alert); - -/**   * i2c_handle_smbus_alert - Handle an SMBus alert   * @ara: the ARA client on the relevant adapter   * Context: can't sleep diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile index 4a67d3199877..6d9d865e8518 100644 --- a/drivers/i2c/muxes/Makefile +++ b/drivers/i2c/muxes/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0  #  # Makefile for multiplexer I2C chip drivers. diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index 7b992db38021..2ca068d8b92d 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -246,36 +246,6 @@ static irqreturn_t pca954x_irq_handler(int irq, void *dev_id)  	return handled ? IRQ_HANDLED : IRQ_NONE;  } -static void pca954x_irq_mask(struct irq_data *idata) -{ -	struct pca954x *data = irq_data_get_irq_chip_data(idata); -	unsigned int pos = idata->hwirq; -	unsigned long flags; - -	raw_spin_lock_irqsave(&data->lock, flags); - -	data->irq_mask &= ~BIT(pos); -	if (!data->irq_mask) -		disable_irq(data->client->irq); - -	raw_spin_unlock_irqrestore(&data->lock, flags); -} - -static void pca954x_irq_unmask(struct irq_data *idata) -{ -	struct pca954x *data = irq_data_get_irq_chip_data(idata); -	unsigned int pos = idata->hwirq; -	unsigned long flags; - -	raw_spin_lock_irqsave(&data->lock, flags); - -	if (!data->irq_mask) -		enable_irq(data->client->irq); -	data->irq_mask |= BIT(pos); - -	raw_spin_unlock_irqrestore(&data->lock, flags); -} -  static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type)  {  	if ((type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_LEVEL_LOW) @@ -285,8 +255,6 @@ static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type)  static struct irq_chip pca954x_irq_chip = {  	.name = "i2c-mux-pca954x", -	.irq_mask = pca954x_irq_mask, -	.irq_unmask = pca954x_irq_unmask,  	.irq_set_type = pca954x_irq_set_type,  }; @@ -294,7 +262,7 @@ static int pca954x_irq_setup(struct i2c_mux_core *muxc)  {  	struct pca954x *data = i2c_mux_priv(muxc);  	struct i2c_client *client = data->client; -	int c, err, irq; +	int c, irq;  	if (!data->chip->has_irq || client->irq <= 0)  		return 0; @@ -309,29 +277,31 @@ static int pca954x_irq_setup(struct i2c_mux_core *muxc)  	for (c = 0; c < data->chip->nchans; c++) {  		irq = irq_create_mapping(data->irq, c); +		if (!irq) { +			dev_err(&client->dev, "failed irq create map\n"); +			return -EINVAL; +		}  		irq_set_chip_data(irq, data);  		irq_set_chip_and_handler(irq, &pca954x_irq_chip,  			handle_simple_irq);  	} -	err = devm_request_threaded_irq(&client->dev, data->client->irq, NULL, -					pca954x_irq_handler, -					IRQF_ONESHOT | IRQF_SHARED, -					"pca954x", data); -	if (err) -		goto err_req_irq; +	return 0; +} -	disable_irq(data->client->irq); +static void pca954x_cleanup(struct i2c_mux_core *muxc) +{ +	struct pca954x *data = i2c_mux_priv(muxc); +	int c, irq; -	return 0; -err_req_irq: -	for (c = 0; c < data->chip->nchans; c++) { -		irq = irq_find_mapping(data->irq, c); -		irq_dispose_mapping(irq); +	if (data->irq) { +		for (c = 0; c < data->chip->nchans; c++) { +			irq = irq_find_mapping(data->irq, c); +			irq_dispose_mapping(irq); +		} +		irq_domain_remove(data->irq);  	} -	irq_domain_remove(data->irq); - -	return err; +	i2c_mux_del_adapters(muxc);  }  /* @@ -391,7 +361,7 @@ static int pca954x_probe(struct i2c_client *client,  	ret = pca954x_irq_setup(muxc);  	if (ret) -		goto fail_del_adapters; +		goto fail_cleanup;  	/* Now create an adapter for each channel */  	for (num = 0; num < data->chip->nchans; num++) { @@ -414,7 +384,16 @@ static int pca954x_probe(struct i2c_client *client,  		ret = i2c_mux_add_adapter(muxc, force, num, class);  		if (ret) -			goto fail_del_adapters; +			goto fail_cleanup; +	} + +	if (data->irq) { +		ret = devm_request_threaded_irq(&client->dev, data->client->irq, +						NULL, pca954x_irq_handler, +						IRQF_ONESHOT | IRQF_SHARED, +						"pca954x", data); +		if (ret) +			goto fail_cleanup;  	}  	dev_info(&client->dev, @@ -424,26 +403,16 @@ static int pca954x_probe(struct i2c_client *client,  	return 0; -fail_del_adapters: -	i2c_mux_del_adapters(muxc); +fail_cleanup: +	pca954x_cleanup(muxc);  	return ret;  }  static int pca954x_remove(struct i2c_client *client)  {  	struct i2c_mux_core *muxc = i2c_get_clientdata(client); -	struct pca954x *data = i2c_mux_priv(muxc); -	int c, irq; -	if (data->irq) { -		for (c = 0; c < data->chip->nchans; c++) { -			irq = irq_find_mapping(data->irq, c); -			irq_dispose_mapping(irq); -		} -		irq_domain_remove(data->irq); -	} - -	i2c_mux_del_adapters(muxc); +	pca954x_cleanup(muxc);  	return 0;  } diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c index d97031804de8..f6c9c3dc6cad 100644 --- a/drivers/i2c/muxes/i2c-mux-reg.c +++ b/drivers/i2c/muxes/i2c-mux-reg.c @@ -107,9 +107,9 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,  	put_device(&adapter->dev);  	mux->data.n_values = of_get_child_count(np); -	if (of_find_property(np, "little-endian", NULL)) { +	if (of_property_read_bool(np, "little-endian")) {  		mux->data.little_endian = true; -	} else if (of_find_property(np, "big-endian", NULL)) { +	} else if (of_property_read_bool(np, "big-endian")) {  		mux->data.little_endian = false;  	} else {  #if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : \ @@ -122,10 +122,7 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,  #error Endianness not defined?  #endif  	} -	if (of_find_property(np, "write-only", NULL)) -		mux->data.write_only = true; -	else -		mux->data.write_only = false; +	mux->data.write_only = of_property_read_bool(np, "write-only");  	values = devm_kzalloc(&pdev->dev,  			      sizeof(*mux->data.values) * mux->data.n_values, |