Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6a7c9243 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull i2c fixes from Wolfram Sang:
 "Some bugfixes from I2C:

   - fix a uevent triggered boot problem by removing a useless debug
     print

   - fix sysfs-attributes of the new i2c-demux-pinctrl driver to follow
     standard kernel behaviour

   - fix a potential division-by-zero error (needed two takes)"

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: jz4780: really prevent potential division by zero
  Revert "i2c: jz4780: prevent potential division by zero"
  i2c: jz4780: prevent potential division by zero
  i2c: mux: demux-pinctrl: Update docs to new sysfs-attributes
  i2c: mux: demux-pinctrl: Clean up sysfs attributes
  i2c: prevent endless uevent loop with CONFIG_I2C_DEBUG_CORE
parents 9f2394c9 caf28080
Loading
Loading
Loading
Loading
+12 −17
Original line number Diff line number Diff line
What:		/sys/devices/platform/<i2c-demux-name>/cur_master
What:		/sys/devices/platform/<i2c-demux-name>/available_masters
Date:		January 2016
KernelVersion:	4.6
Contact:	Wolfram Sang <wsa@the-dreams.de>
Description:
		Reading the file will give you a list of masters which can be
		selected for a demultiplexed bus. The format is
		"<index>:<name>". Example from a Renesas Lager board:

This file selects the active I2C master for a demultiplexed bus.
		0:/i2c@e6500000 1:/i2c@e6508000

Write 0 there for the first master, 1 for the second etc. Reading the file will
give you a list with the active master marked. Example from a Renesas Lager
board:

root@Lager:~# cat /sys/devices/platform/i2c@8/cur_master
* 0 - /i2c@9
  1 - /i2c@e6520000
  2 - /i2c@e6530000

root@Lager:~# echo 2 > /sys/devices/platform/i2c@8/cur_master

root@Lager:~# cat /sys/devices/platform/i2c@8/cur_master
  0 - /i2c@9
  1 - /i2c@e6520000
* 2 - /i2c@e6530000
What:		/sys/devices/platform/<i2c-demux-name>/current_master
Date:		January 2016
KernelVersion:	4.6
Contact:	Wolfram Sang <wsa@the-dreams.de>
Description:
		This file selects/shows the active I2C master for a demultiplexed
		bus. It uses the <index> value from the file 'available_masters'.
+6 −1
Original line number Diff line number Diff line
@@ -771,11 +771,16 @@ static int jz4780_i2c_probe(struct platform_device *pdev)
	ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
				   &clk_freq);
	if (ret) {
		dev_err(&pdev->dev, "clock-frequency not specified in DT");
		dev_err(&pdev->dev, "clock-frequency not specified in DT\n");
		goto err;
	}

	i2c->speed = clk_freq / 1000;
	if (i2c->speed == 0) {
		ret = -EINVAL;
		dev_err(&pdev->dev, "clock-frequency minimum is 1000\n");
		goto err;
	}
	jz4780_i2c_set_speed(i2c);

	dev_info(&pdev->dev, "Bus frequency is %d KHz\n", i2c->speed);
+2 −8
Original line number Diff line number Diff line
@@ -525,8 +525,6 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
	return 0;
}


/* uevent helps with hotplug: modprobe -q $(MODALIAS) */
static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
{
	struct i2c_client *client = to_i2c_client(dev);
@@ -536,11 +534,7 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
	if (rc != -ENODEV)
		return rc;

	if (add_uevent_var(env, "MODALIAS=%s%s",
			   I2C_MODULE_PREFIX, client->name))
		return -ENOMEM;
	dev_dbg(dev, "uevent\n");
	return 0;
	return add_uevent_var(env, "MODALIAS=%s%s", I2C_MODULE_PREFIX, client->name);
}

/* i2c bus recovery routines */
+29 −10
Original line number Diff line number Diff line
@@ -140,21 +140,33 @@ static int i2c_demux_change_master(struct i2c_demux_pinctrl_priv *priv, u32 new_
	return i2c_demux_activate_master(priv, new_chan);
}

static ssize_t cur_master_show(struct device *dev, struct device_attribute *attr,
static ssize_t available_masters_show(struct device *dev,
				      struct device_attribute *attr,
				      char *buf)
{
	struct i2c_demux_pinctrl_priv *priv = dev_get_drvdata(dev);
	int count = 0, i;

	for (i = 0; i < priv->num_chan && count < PAGE_SIZE; i++)
		count += scnprintf(buf + count, PAGE_SIZE - count, "%c %d - %s\n",
				 i == priv->cur_chan ? '*' : ' ', i,
				 priv->chan[i].parent_np->full_name);
		count += scnprintf(buf + count, PAGE_SIZE - count, "%d:%s%c",
				   i, priv->chan[i].parent_np->full_name,
				   i == priv->num_chan - 1 ? '\n' : ' ');

	return count;
}
static DEVICE_ATTR_RO(available_masters);

static ssize_t cur_master_store(struct device *dev, struct device_attribute *attr,
static ssize_t current_master_show(struct device *dev,
				   struct device_attribute *attr,
				   char *buf)
{
	struct i2c_demux_pinctrl_priv *priv = dev_get_drvdata(dev);

	return sprintf(buf, "%d\n", priv->cur_chan);
}

static ssize_t current_master_store(struct device *dev,
				    struct device_attribute *attr,
				    const char *buf, size_t count)
{
	struct i2c_demux_pinctrl_priv *priv = dev_get_drvdata(dev);
@@ -172,7 +184,7 @@ static ssize_t cur_master_store(struct device *dev, struct device_attribute *att

	return ret < 0 ? ret : count;
}
static DEVICE_ATTR_RW(cur_master);
static DEVICE_ATTR_RW(current_master);

static int i2c_demux_pinctrl_probe(struct platform_device *pdev)
{
@@ -218,12 +230,18 @@ static int i2c_demux_pinctrl_probe(struct platform_device *pdev)
	/* switch to first parent as active master */
	i2c_demux_activate_master(priv, 0);

	err = device_create_file(&pdev->dev, &dev_attr_cur_master);
	err = device_create_file(&pdev->dev, &dev_attr_available_masters);
	if (err)
		goto err_rollback;

	err = device_create_file(&pdev->dev, &dev_attr_current_master);
	if (err)
		goto err_rollback_available;

	return 0;

err_rollback_available:
	device_remove_file(&pdev->dev, &dev_attr_available_masters);
err_rollback:
	for (j = 0; j < i; j++) {
		of_node_put(priv->chan[j].parent_np);
@@ -238,7 +256,8 @@ static int i2c_demux_pinctrl_remove(struct platform_device *pdev)
	struct i2c_demux_pinctrl_priv *priv = platform_get_drvdata(pdev);
	int i;

	device_remove_file(&pdev->dev, &dev_attr_cur_master);
	device_remove_file(&pdev->dev, &dev_attr_current_master);
	device_remove_file(&pdev->dev, &dev_attr_available_masters);

	i2c_demux_deactivate_master(priv);