提交 370136bc 编写于 作者: M Maxime Ripard 提交者: Wolfram Sang

i2c: mv64xxx: Add reset deassert call

The Allwinner A31 SoC using that IP has a reset controller maintaining
it reset unless told otherwise.

Add some optional reset support to the driver.
Signed-off-by: NMaxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: NGregory CLEMENT <gregory.clement@free-electrons.com>
Tested-by: NGregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: NWolfram Sang <wsa@the-dreams.de>
上级 96c4b6bb
...@@ -16,6 +16,7 @@ Optional properties : ...@@ -16,6 +16,7 @@ Optional properties :
- clock-frequency : Desired I2C bus clock frequency in Hz. If not set the - clock-frequency : Desired I2C bus clock frequency in Hz. If not set the
default frequency is 100kHz default frequency is 100kHz
- resets : phandle to the parent reset controller
Examples: Examples:
......
...@@ -528,6 +528,7 @@ config I2C_MPC ...@@ -528,6 +528,7 @@ config I2C_MPC
config I2C_MV64XXX config I2C_MV64XXX
tristate "Marvell mv64xxx I2C Controller" tristate "Marvell mv64xxx I2C Controller"
depends on (MV64X60 || PLAT_ORION || ARCH_SUNXI) depends on (MV64X60 || PLAT_ORION || ARCH_SUNXI)
select RESET_CONTROLLER
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
built-in I2C interface on the Marvell 64xxx line of host bridges. built-in I2C interface on the Marvell 64xxx line of host bridges.
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/mv643xx_i2c.h> #include <linux/mv643xx_i2c.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
...@@ -148,6 +149,7 @@ struct mv64xxx_i2c_data { ...@@ -148,6 +149,7 @@ struct mv64xxx_i2c_data {
bool offload_enabled; bool offload_enabled;
/* 5us delay in order to avoid repeated start timing violation */ /* 5us delay in order to avoid repeated start timing violation */
bool errata_delay; bool errata_delay;
struct reset_control *rstc;
}; };
static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = { static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = {
...@@ -759,6 +761,16 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, ...@@ -759,6 +761,16 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
} }
drv_data->irq = irq_of_parse_and_map(np, 0); drv_data->irq = irq_of_parse_and_map(np, 0);
drv_data->rstc = devm_reset_control_get(dev, NULL);
if (IS_ERR(drv_data->rstc)) {
if (PTR_ERR(drv_data->rstc) == -EPROBE_DEFER) {
rc = -EPROBE_DEFER;
goto out;
}
} else {
reset_control_deassert(drv_data->rstc);
}
/* Its not yet defined how timeouts will be specified in device tree. /* Its not yet defined how timeouts will be specified in device tree.
* So hard code the value to 1 second. * So hard code the value to 1 second.
*/ */
...@@ -845,7 +857,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) ...@@ -845,7 +857,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
} }
if (drv_data->irq < 0) { if (drv_data->irq < 0) {
rc = -ENXIO; rc = -ENXIO;
goto exit_clk; goto exit_reset;
} }
drv_data->adapter.dev.parent = &pd->dev; drv_data->adapter.dev.parent = &pd->dev;
...@@ -865,7 +877,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) ...@@ -865,7 +877,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
dev_err(&drv_data->adapter.dev, dev_err(&drv_data->adapter.dev,
"mv64xxx: Can't register intr handler irq%d: %d\n", "mv64xxx: Can't register intr handler irq%d: %d\n",
drv_data->irq, rc); drv_data->irq, rc);
goto exit_clk; goto exit_reset;
} else if ((rc = i2c_add_numbered_adapter(&drv_data->adapter)) != 0) { } else if ((rc = i2c_add_numbered_adapter(&drv_data->adapter)) != 0) {
dev_err(&drv_data->adapter.dev, dev_err(&drv_data->adapter.dev,
"mv64xxx: Can't add i2c adapter, rc: %d\n", -rc); "mv64xxx: Can't add i2c adapter, rc: %d\n", -rc);
...@@ -876,6 +888,9 @@ mv64xxx_i2c_probe(struct platform_device *pd) ...@@ -876,6 +888,9 @@ mv64xxx_i2c_probe(struct platform_device *pd)
exit_free_irq: exit_free_irq:
free_irq(drv_data->irq, drv_data); free_irq(drv_data->irq, drv_data);
exit_reset:
if (pd->dev.of_node && !IS_ERR(drv_data->rstc))
reset_control_assert(drv_data->rstc);
exit_clk: exit_clk:
#if defined(CONFIG_HAVE_CLK) #if defined(CONFIG_HAVE_CLK)
/* Not all platforms have a clk */ /* Not all platforms have a clk */
...@@ -894,6 +909,8 @@ mv64xxx_i2c_remove(struct platform_device *dev) ...@@ -894,6 +909,8 @@ mv64xxx_i2c_remove(struct platform_device *dev)
i2c_del_adapter(&drv_data->adapter); i2c_del_adapter(&drv_data->adapter);
free_irq(drv_data->irq, drv_data); free_irq(drv_data->irq, drv_data);
if (dev->dev.of_node && !IS_ERR(drv_data->rstc))
reset_control_assert(drv_data->rstc);
#if defined(CONFIG_HAVE_CLK) #if defined(CONFIG_HAVE_CLK)
/* Not all platforms have a clk */ /* Not all platforms have a clk */
if (!IS_ERR(drv_data->clk)) { if (!IS_ERR(drv_data->clk)) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册