Commit 6a7c9243 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

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
What: /sys/devices/platform/<i2c-demux-name>/cur_master What: /sys/devices/platform/<i2c-demux-name>/available_masters
Date: January 2016 Date: January 2016
KernelVersion: 4.6 KernelVersion: 4.6
Contact: Wolfram Sang <wsa@the-dreams.de> Contact: Wolfram Sang <wsa@the-dreams.de>
Description: 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 What: /sys/devices/platform/<i2c-demux-name>/current_master
give you a list with the active master marked. Example from a Renesas Lager Date: January 2016
board: KernelVersion: 4.6
Contact: Wolfram Sang <wsa@the-dreams.de>
root@Lager:~# cat /sys/devices/platform/i2c@8/cur_master Description:
* 0 - /i2c@9 This file selects/shows the active I2C master for a demultiplexed
1 - /i2c@e6520000 bus. It uses the <index> value from the file 'available_masters'.
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
...@@ -771,11 +771,16 @@ static int jz4780_i2c_probe(struct platform_device *pdev) ...@@ -771,11 +771,16 @@ static int jz4780_i2c_probe(struct platform_device *pdev)
ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
&clk_freq); &clk_freq);
if (ret) { 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; goto err;
} }
i2c->speed = clk_freq / 1000; 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); jz4780_i2c_set_speed(i2c);
dev_info(&pdev->dev, "Bus frequency is %d KHz\n", i2c->speed); dev_info(&pdev->dev, "Bus frequency is %d KHz\n", i2c->speed);
......
...@@ -525,22 +525,16 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv) ...@@ -525,22 +525,16 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
return 0; return 0;
} }
/* uevent helps with hotplug: modprobe -q $(MODALIAS) */
static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
int rc; int rc;
rc = acpi_device_uevent_modalias(dev, env); rc = acpi_device_uevent_modalias(dev, env);
if (rc != -ENODEV) if (rc != -ENODEV)
return rc; return rc;
if (add_uevent_var(env, "MODALIAS=%s%s", return add_uevent_var(env, "MODALIAS=%s%s", I2C_MODULE_PREFIX, client->name);
I2C_MODULE_PREFIX, client->name))
return -ENOMEM;
dev_dbg(dev, "uevent\n");
return 0;
} }
/* i2c bus recovery routines */ /* i2c bus recovery routines */
......
...@@ -140,22 +140,34 @@ static int i2c_demux_change_master(struct i2c_demux_pinctrl_priv *priv, u32 new_ ...@@ -140,22 +140,34 @@ static int i2c_demux_change_master(struct i2c_demux_pinctrl_priv *priv, u32 new_
return i2c_demux_activate_master(priv, new_chan); 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,
char *buf) struct device_attribute *attr,
char *buf)
{ {
struct i2c_demux_pinctrl_priv *priv = dev_get_drvdata(dev); struct i2c_demux_pinctrl_priv *priv = dev_get_drvdata(dev);
int count = 0, i; int count = 0, i;
for (i = 0; i < priv->num_chan && count < PAGE_SIZE; i++) for (i = 0; i < priv->num_chan && count < PAGE_SIZE; i++)
count += scnprintf(buf + count, PAGE_SIZE - count, "%c %d - %s\n", count += scnprintf(buf + count, PAGE_SIZE - count, "%d:%s%c",
i == priv->cur_chan ? '*' : ' ', i, i, priv->chan[i].parent_np->full_name,
priv->chan[i].parent_np->full_name); i == priv->num_chan - 1 ? '\n' : ' ');
return count; 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,
const char *buf, size_t count) 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); struct i2c_demux_pinctrl_priv *priv = dev_get_drvdata(dev);
unsigned int val; unsigned int val;
...@@ -172,7 +184,7 @@ static ssize_t cur_master_store(struct device *dev, struct device_attribute *att ...@@ -172,7 +184,7 @@ static ssize_t cur_master_store(struct device *dev, struct device_attribute *att
return ret < 0 ? ret : count; 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) static int i2c_demux_pinctrl_probe(struct platform_device *pdev)
{ {
...@@ -218,12 +230,18 @@ 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 */ /* switch to first parent as active master */
i2c_demux_activate_master(priv, 0); 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) if (err)
goto err_rollback; goto err_rollback;
err = device_create_file(&pdev->dev, &dev_attr_current_master);
if (err)
goto err_rollback_available;
return 0; return 0;
err_rollback_available:
device_remove_file(&pdev->dev, &dev_attr_available_masters);
err_rollback: err_rollback:
for (j = 0; j < i; j++) { for (j = 0; j < i; j++) {
of_node_put(priv->chan[j].parent_np); of_node_put(priv->chan[j].parent_np);
...@@ -238,7 +256,8 @@ static int i2c_demux_pinctrl_remove(struct platform_device *pdev) ...@@ -238,7 +256,8 @@ static int i2c_demux_pinctrl_remove(struct platform_device *pdev)
struct i2c_demux_pinctrl_priv *priv = platform_get_drvdata(pdev); struct i2c_demux_pinctrl_priv *priv = platform_get_drvdata(pdev);
int i; 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); i2c_demux_deactivate_master(priv);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment