aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhangfei Gao <zhangfei.gao@linaro.org>2016-12-27 09:22:40 -0500
committerWolfram Sang <wsa@the-dreams.de>2017-03-08 12:15:18 -0500
commitab809fd81fde3d416f8656d8f814a0777fb9b65e (patch)
tree18784d3b6c72ae0f3f87a1820e2c68fa5f78ad67
parent3b0277f198ac928f323c42e180680d2f79aa980d (diff)
i2c: designware: add reset interface
Some platforms like hi3660 need do reset first to allow accessing registers Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Tested-by: Ramiro Oliveira <ramiro.oliveira@synopsys.com> Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r--drivers/i2c/busses/i2c-designware-core.h1
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c28
2 files changed, 25 insertions, 4 deletions
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index c1db3a5a340f..d9aaf1790e0e 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -88,6 +88,7 @@ struct dw_i2c_dev {
88 void __iomem *base; 88 void __iomem *base;
89 struct completion cmd_complete; 89 struct completion cmd_complete;
90 struct clk *clk; 90 struct clk *clk;
91 struct reset_control *rst;
91 u32 (*get_clk_rate_khz) (struct dw_i2c_dev *dev); 92 u32 (*get_clk_rate_khz) (struct dw_i2c_dev *dev);
92 struct dw_pci_controller *controller; 93 struct dw_pci_controller *controller;
93 int cmd_err; 94 int cmd_err;
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 6ce431323125..79c4b4ea0539 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -38,6 +38,7 @@
38#include <linux/pm_runtime.h> 38#include <linux/pm_runtime.h>
39#include <linux/property.h> 39#include <linux/property.h>
40#include <linux/io.h> 40#include <linux/io.h>
41#include <linux/reset.h>
41#include <linux/slab.h> 42#include <linux/slab.h>
42#include <linux/acpi.h> 43#include <linux/acpi.h>
43#include <linux/platform_data/i2c-designware.h> 44#include <linux/platform_data/i2c-designware.h>
@@ -199,6 +200,14 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
199 dev->irq = irq; 200 dev->irq = irq;
200 platform_set_drvdata(pdev, dev); 201 platform_set_drvdata(pdev, dev);
201 202
203 dev->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
204 if (IS_ERR(dev->rst)) {
205 if (PTR_ERR(dev->rst) == -EPROBE_DEFER)
206 return -EPROBE_DEFER;
207 } else {
208 reset_control_deassert(dev->rst);
209 }
210
202 if (pdata) { 211 if (pdata) {
203 dev->clk_freq = pdata->i2c_scl_freq; 212 dev->clk_freq = pdata->i2c_scl_freq;
204 } else { 213 } else {
@@ -235,12 +244,13 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
235 && dev->clk_freq != 1000000 && dev->clk_freq != 3400000) { 244 && dev->clk_freq != 1000000 && dev->clk_freq != 3400000) {
236 dev_err(&pdev->dev, 245 dev_err(&pdev->dev,
237 "Only 100kHz, 400kHz, 1MHz and 3.4MHz supported"); 246 "Only 100kHz, 400kHz, 1MHz and 3.4MHz supported");
238 return -EINVAL; 247 r = -EINVAL;
248 goto exit_reset;
239 } 249 }
240 250
241 r = i2c_dw_eval_lock_support(dev); 251 r = i2c_dw_eval_lock_support(dev);
242 if (r) 252 if (r)
243 return r; 253 goto exit_reset;
244 254
245 dev->functionality = I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY; 255 dev->functionality = I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY;
246 256
@@ -286,10 +296,18 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
286 } 296 }
287 297
288 r = i2c_dw_probe(dev); 298 r = i2c_dw_probe(dev);
289 if (r && !dev->pm_runtime_disabled) 299 if (r)
290 pm_runtime_disable(&pdev->dev); 300 goto exit_probe;
291 301
292 return r; 302 return r;
303
304exit_probe:
305 if (!dev->pm_runtime_disabled)
306 pm_runtime_disable(&pdev->dev);
307exit_reset:
308 if (!IS_ERR_OR_NULL(dev->rst))
309 reset_control_assert(dev->rst);
310 return r;
293} 311}
294 312
295static int dw_i2c_plat_remove(struct platform_device *pdev) 313static int dw_i2c_plat_remove(struct platform_device *pdev)
@@ -306,6 +324,8 @@ static int dw_i2c_plat_remove(struct platform_device *pdev)
306 pm_runtime_put_sync(&pdev->dev); 324 pm_runtime_put_sync(&pdev->dev);
307 if (!dev->pm_runtime_disabled) 325 if (!dev->pm_runtime_disabled)
308 pm_runtime_disable(&pdev->dev); 326 pm_runtime_disable(&pdev->dev);
327 if (!IS_ERR_OR_NULL(dev->rst))
328 reset_control_assert(dev->rst);
309 329
310 return 0; 330 return 0;
311} 331}