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
This commit is contained in:
commit
6a7c924314
|
@ -1,23 +1,18 @@
|
||||||
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)
|
||||||
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)
|
||||||
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_
|
||||||
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
|
||||||
|
|
||||||
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)
|
||||||
/* 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)
|
||||||
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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue