From f2326401b8ff8a646092562d272ed50d9cf99c6c Mon Sep 17 00:00:00 2001 From: Jun Gao Date: Mon, 17 Jul 2017 19:02:10 +0800 Subject: i2c: mediatek: send i2c master code at 400k The speed of sending i2c master code in high-speed mode depends on source clock, clock-div and TIMING register. The source clock and clock-div of different SoC are not all the same. In order to send i2c master code at 400k in high-speed mode, a appropriate value should be set to TIMING register for a certain source clock and clock-div. Signed-off-by: Jun Gao Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mt65xx.c | 65 +++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index 45d61714c81b..9bedf0bf2c4d 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -50,7 +50,6 @@ #define I2C_FS_START_CON 0x1800 #define I2C_TIME_CLR_VALUE 0x0000 #define I2C_TIME_DEFAULT_VALUE 0x0003 -#define I2C_FS_TIME_INIT_VALUE 0x1303 #define I2C_WRRD_TRANAC_VALUE 0x0002 #define I2C_RD_TRANAC_VALUE 0x0001 @@ -154,6 +153,7 @@ struct mtk_i2c { bool use_push_pull; /* IO config push-pull mode */ u16 irq_stat; /* interrupt status */ + unsigned int clk_src_div; unsigned int speed_hz; /* The speed in transfer */ enum mtk_trans_op op; u16 timing_reg; @@ -285,23 +285,20 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c) * less than or equal to i2c->speed_hz. The calculation try to get * sample_cnt and step_cn */ -static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk, - unsigned int clock_div) +static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src, + unsigned int target_speed, + unsigned int *timing_step_cnt, + unsigned int *timing_sample_cnt) { - unsigned int clk_src; unsigned int step_cnt; unsigned int sample_cnt; unsigned int max_step_cnt; - unsigned int target_speed; unsigned int base_sample_cnt = MAX_SAMPLE_CNT_DIV; unsigned int base_step_cnt; unsigned int opt_div; unsigned int best_mul; unsigned int cnt_mul; - clk_src = parent_clk / clock_div; - target_speed = i2c->speed_hz; - if (target_speed > MAX_HS_MODE_SPEED) target_speed = MAX_HS_MODE_SPEED; @@ -347,16 +344,48 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk, return -EINVAL; } - step_cnt--; - sample_cnt--; + *timing_step_cnt = step_cnt - 1; + *timing_sample_cnt = sample_cnt - 1; + + return 0; +} + +static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk) +{ + unsigned int clk_src; + unsigned int step_cnt; + unsigned int sample_cnt; + unsigned int target_speed; + int ret; + + clk_src = parent_clk / i2c->clk_src_div; + target_speed = i2c->speed_hz; if (target_speed > MAX_FS_MODE_SPEED) { + /* Set master code speed register */ + ret = mtk_i2c_calculate_speed(i2c, clk_src, MAX_FS_MODE_SPEED, + &step_cnt, &sample_cnt); + if (ret < 0) + return ret; + + i2c->timing_reg = (sample_cnt << 8) | step_cnt; + /* Set the high speed mode register */ - i2c->timing_reg = I2C_FS_TIME_INIT_VALUE; + ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed, + &step_cnt, &sample_cnt); + if (ret < 0) + return ret; + i2c->high_speed_reg = I2C_TIME_DEFAULT_VALUE | (sample_cnt << 12) | (step_cnt << 8); } else { - i2c->timing_reg = (sample_cnt << 8) | (step_cnt << 0); + ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed, + &step_cnt, &sample_cnt); + if (ret < 0) + return ret; + + i2c->timing_reg = (sample_cnt << 8) | step_cnt; + /* Disable the high speed transaction */ i2c->high_speed_reg = I2C_TIME_CLR_VALUE; } @@ -647,8 +676,7 @@ static const struct i2c_algorithm mtk_i2c_algorithm = { .functionality = mtk_i2c_functionality, }; -static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c, - unsigned int *clk_src_div) +static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c) { int ret; @@ -656,11 +684,11 @@ static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c, if (ret < 0) i2c->speed_hz = I2C_DEFAULT_SPEED; - ret = of_property_read_u32(np, "clock-div", clk_src_div); + ret = of_property_read_u32(np, "clock-div", &i2c->clk_src_div); if (ret < 0) return ret; - if (*clk_src_div == 0) + if (i2c->clk_src_div == 0) return -EINVAL; i2c->have_pmic = of_property_read_bool(np, "mediatek,have-pmic"); @@ -676,7 +704,6 @@ static int mtk_i2c_probe(struct platform_device *pdev) int ret = 0; struct mtk_i2c *i2c; struct clk *clk; - unsigned int clk_src_div; struct resource *res; int irq; @@ -684,7 +711,7 @@ static int mtk_i2c_probe(struct platform_device *pdev) if (!i2c) return -ENOMEM; - ret = mtk_i2c_parse_dt(pdev->dev.of_node, i2c, &clk_src_div); + ret = mtk_i2c_parse_dt(pdev->dev.of_node, i2c); if (ret) return -EINVAL; @@ -745,7 +772,7 @@ static int mtk_i2c_probe(struct platform_device *pdev) strlcpy(i2c->adap.name, I2C_DRV_NAME, sizeof(i2c->adap.name)); - ret = mtk_i2c_set_speed(i2c, clk_get_rate(clk), clk_src_div); + ret = mtk_i2c_set_speed(i2c, clk_get_rate(clk)); if (ret) { dev_err(&pdev->dev, "Failed to set the speed.\n"); return -EINVAL; -- cgit v1.2.3 From 9242e72aaea05c0fce2003a8efa48f403d87a5bf Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 28 Jul 2017 01:16:24 +0900 Subject: i2c: use dev_get_drvdata() to get private data in suspend/resume hooks Several drivers call to_platform_device() to get platform_device and pass it to platform_get_drvdata(). In platform_get_drvdata(), the platform_device is converted back to struct device again. Use dev_get_drvdata() to avoid platform_device/device dance. Signed-off-by: Masahiro Yamada Reviewed-by: Andy Shevchenko (for DesignWare only) Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-bcm-iproc.c | 6 ++---- drivers/i2c/busses/i2c-cadence.c | 6 ++---- drivers/i2c/busses/i2c-davinci.c | 6 ++---- drivers/i2c/busses/i2c-designware-platdrv.c | 6 ++---- drivers/i2c/busses/i2c-exynos5.c | 6 ++---- drivers/i2c/busses/i2c-hix5hd2.c | 6 ++---- drivers/i2c/busses/i2c-lpc2k.c | 6 ++---- drivers/i2c/busses/i2c-mv64xxx.c | 3 +-- drivers/i2c/busses/i2c-pxa.c | 6 ++---- drivers/i2c/busses/i2c-s3c2410.c | 6 ++---- drivers/i2c/busses/i2c-sirf.c | 6 ++---- drivers/i2c/busses/i2c-st.c | 3 +-- drivers/i2c/busses/i2c-xiic.c | 6 ++---- 13 files changed, 24 insertions(+), 48 deletions(-) diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index 318df559adc5..4c8c3bc4669c 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -510,8 +510,7 @@ static int bcm_iproc_i2c_remove(struct platform_device *pdev) static int bcm_iproc_i2c_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct bcm_iproc_i2c_dev *iproc_i2c = platform_get_drvdata(pdev); + struct bcm_iproc_i2c_dev *iproc_i2c = dev_get_drvdata(dev); /* make sure there's no pending interrupt when we go into suspend */ writel(0, iproc_i2c->base + IE_OFFSET); @@ -526,8 +525,7 @@ static int bcm_iproc_i2c_suspend(struct device *dev) static int bcm_iproc_i2c_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct bcm_iproc_i2c_dev *iproc_i2c = platform_get_drvdata(pdev); + struct bcm_iproc_i2c_dev *iproc_i2c = dev_get_drvdata(dev); int ret; u32 val; diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 75d80161931f..b13605718291 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -826,8 +826,7 @@ static int cdns_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long */ static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct cdns_i2c *xi2c = platform_get_drvdata(pdev); + struct cdns_i2c *xi2c = dev_get_drvdata(dev); clk_disable(xi2c->clk); @@ -844,8 +843,7 @@ static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev) */ static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct cdns_i2c *xi2c = platform_get_drvdata(pdev); + struct cdns_i2c *xi2c = dev_get_drvdata(dev); int ret; ret = clk_enable(xi2c->clk); diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 9e7ef5cf5d49..9163a1c9bddc 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -876,8 +876,7 @@ static int davinci_i2c_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int davinci_i2c_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct davinci_i2c_dev *i2c_dev = platform_get_drvdata(pdev); + struct davinci_i2c_dev *i2c_dev = dev_get_drvdata(dev); /* put I2C into reset */ davinci_i2c_reset_ctrl(i2c_dev, 0); @@ -888,8 +887,7 @@ static int davinci_i2c_suspend(struct device *dev) static int davinci_i2c_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct davinci_i2c_dev *i2c_dev = platform_get_drvdata(pdev); + struct davinci_i2c_dev *i2c_dev = dev_get_drvdata(dev); clk_prepare_enable(i2c_dev->clk); /* take I2C out of reset */ diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 2ea6d0d25a01..abe1eca8d689 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -428,8 +428,7 @@ static void dw_i2c_plat_complete(struct device *dev) #ifdef CONFIG_PM static int dw_i2c_plat_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev); + struct dw_i2c_dev *i_dev = dev_get_drvdata(dev); i_dev->disable(i_dev); i2c_dw_plat_prepare_clk(i_dev, false); @@ -439,8 +438,7 @@ static int dw_i2c_plat_suspend(struct device *dev) static int dw_i2c_plat_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev); + struct dw_i2c_dev *i_dev = dev_get_drvdata(dev); i2c_dw_plat_prepare_clk(i_dev, true); i_dev->init(i_dev); diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index 23ed4d67ecad..3855e0b11877 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -803,8 +803,7 @@ static int exynos5_i2c_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int exynos5_i2c_suspend_noirq(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct exynos5_i2c *i2c = platform_get_drvdata(pdev); + struct exynos5_i2c *i2c = dev_get_drvdata(dev); i2c->suspended = 1; @@ -815,8 +814,7 @@ static int exynos5_i2c_suspend_noirq(struct device *dev) static int exynos5_i2c_resume_noirq(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct exynos5_i2c *i2c = platform_get_drvdata(pdev); + struct exynos5_i2c *i2c = dev_get_drvdata(dev); int ret = 0; ret = clk_prepare_enable(i2c->clk); diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c index ae7f3180f7e8..bb68957d3da5 100644 --- a/drivers/i2c/busses/i2c-hix5hd2.c +++ b/drivers/i2c/busses/i2c-hix5hd2.c @@ -505,8 +505,7 @@ static int hix5hd2_i2c_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int hix5hd2_i2c_runtime_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct hix5hd2_i2c_priv *priv = platform_get_drvdata(pdev); + struct hix5hd2_i2c_priv *priv = dev_get_drvdata(dev); clk_disable_unprepare(priv->clk); @@ -515,8 +514,7 @@ static int hix5hd2_i2c_runtime_suspend(struct device *dev) static int hix5hd2_i2c_runtime_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct hix5hd2_i2c_priv *priv = platform_get_drvdata(pdev); + struct hix5hd2_i2c_priv *priv = dev_get_drvdata(dev); clk_prepare_enable(priv->clk); hix5hd2_i2c_init(priv); diff --git a/drivers/i2c/busses/i2c-lpc2k.c b/drivers/i2c/busses/i2c-lpc2k.c index 9b1fef455a89..59167c018ae7 100644 --- a/drivers/i2c/busses/i2c-lpc2k.c +++ b/drivers/i2c/busses/i2c-lpc2k.c @@ -457,8 +457,7 @@ static int i2c_lpc2k_remove(struct platform_device *dev) #ifdef CONFIG_PM static int i2c_lpc2k_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct lpc2k_i2c *i2c = platform_get_drvdata(pdev); + struct lpc2k_i2c *i2c = dev_get_drvdata(dev); clk_disable(i2c->clk); @@ -467,8 +466,7 @@ static int i2c_lpc2k_suspend(struct device *dev) static int i2c_lpc2k_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct lpc2k_i2c *i2c = platform_get_drvdata(pdev); + struct lpc2k_i2c *i2c = dev_get_drvdata(dev); clk_enable(i2c->clk); i2c_lpc2k_reset(i2c); diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 5c4db65c5019..b2ef32b188e1 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -975,8 +975,7 @@ mv64xxx_i2c_remove(struct platform_device *dev) #ifdef CONFIG_PM static int mv64xxx_i2c_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct mv64xxx_i2c_data *drv_data = platform_get_drvdata(pdev); + struct mv64xxx_i2c_data *drv_data = dev_get_drvdata(dev); mv64xxx_i2c_hw_init(drv_data); diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 6cf333ecc8b8..600d264e080c 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -1346,8 +1346,7 @@ static int i2c_pxa_remove(struct platform_device *dev) #ifdef CONFIG_PM static int i2c_pxa_suspend_noirq(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct pxa_i2c *i2c = platform_get_drvdata(pdev); + struct pxa_i2c *i2c = dev_get_drvdata(dev); clk_disable(i2c->clk); @@ -1356,8 +1355,7 @@ static int i2c_pxa_suspend_noirq(struct device *dev) static int i2c_pxa_resume_noirq(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct pxa_i2c *i2c = platform_get_drvdata(pdev); + struct pxa_i2c *i2c = dev_get_drvdata(dev); clk_enable(i2c->clk); i2c_pxa_reset(i2c); diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 499af26e736e..5d97510ee48b 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -1246,8 +1246,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int s3c24xx_i2c_suspend_noirq(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); + struct s3c24xx_i2c *i2c = dev_get_drvdata(dev); i2c->suspended = 1; @@ -1259,8 +1258,7 @@ static int s3c24xx_i2c_suspend_noirq(struct device *dev) static int s3c24xx_i2c_resume_noirq(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); + struct s3c24xx_i2c *i2c = dev_get_drvdata(dev); int ret; if (!IS_ERR(i2c->sysreg)) diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index 95e81d0f72b4..2fd8b6d00391 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c @@ -421,8 +421,7 @@ static int i2c_sirfsoc_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int i2c_sirfsoc_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct i2c_adapter *adapter = platform_get_drvdata(pdev); + struct i2c_adapter *adapter = dev_get_drvdata(dev); struct sirfsoc_i2c *siic = adapter->algo_data; clk_enable(siic->clk); @@ -434,8 +433,7 @@ static int i2c_sirfsoc_suspend(struct device *dev) static int i2c_sirfsoc_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct i2c_adapter *adapter = platform_get_drvdata(pdev); + struct i2c_adapter *adapter = dev_get_drvdata(dev); struct sirfsoc_i2c *siic = adapter->algo_data; clk_enable(siic->clk); diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c index 1eb9fa82dcfd..9e62f893958a 100644 --- a/drivers/i2c/busses/i2c-st.c +++ b/drivers/i2c/busses/i2c-st.c @@ -745,8 +745,7 @@ static int st_i2c_xfer(struct i2c_adapter *i2c_adap, #ifdef CONFIG_PM_SLEEP static int st_i2c_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct st_i2c_dev *i2c_dev = platform_get_drvdata(pdev); + struct st_i2c_dev *i2c_dev = dev_get_drvdata(dev); if (i2c_dev->busy) return -EBUSY; diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 66bce3b311a1..34b27bfe72ba 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -853,8 +853,7 @@ MODULE_DEVICE_TABLE(of, xiic_of_match); static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct xiic_i2c *i2c = platform_get_drvdata(pdev); + struct xiic_i2c *i2c = dev_get_drvdata(dev); clk_disable(i2c->clk); @@ -863,8 +862,7 @@ static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev) static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct xiic_i2c *i2c = platform_get_drvdata(pdev); + struct xiic_i2c *i2c = dev_get_drvdata(dev); int ret; ret = clk_enable(i2c->clk); -- cgit v1.2.3 From 453a237ccffad899ce15fb61e871e4784004be17 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 18 Jul 2017 16:43:06 -0500 Subject: i2c: Convert to using %pOF instead of full_name Now that we have a custom printf format specifier, convert users of full_name to use %pOF instead. This is preparation to remove storing of the full path string for each node. Signed-off-by: Rob Herring Acked-by: Maxime Ripard Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-gpio.c | 4 ++-- drivers/i2c/busses/i2c-powermac.c | 10 ++++------ drivers/i2c/busses/i2c-sun6i-p2wi.c | 4 ++-- drivers/i2c/i2c-core-of.c | 24 +++++++++++------------- drivers/i2c/muxes/i2c-demux-pinctrl.c | 4 ++-- 5 files changed, 21 insertions(+), 25 deletions(-) diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index 34cfc0ebdcb9..0ef8fcc6ac3a 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -98,8 +98,8 @@ static int of_i2c_gpio_get_pins(struct device_node *np, return -EPROBE_DEFER; if (!gpio_is_valid(*sda_pin) || !gpio_is_valid(*scl_pin)) { - pr_err("%s: invalid GPIO pins, sda=%d/scl=%d\n", - np->full_name, *sda_pin, *scl_pin); + pr_err("%pOF: invalid GPIO pins, sda=%d/scl=%d\n", + np, *sda_pin, *scl_pin); return -ENODEV; } diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index b0d9dee14a7e..ef9c858fe1d4 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -234,7 +234,7 @@ static u32 i2c_powermac_get_addr(struct i2c_adapter *adap, else if (!strcmp(node->name, "deq")) return 0x34; - dev_warn(&adap->dev, "No i2c address for %s\n", node->full_name); + dev_warn(&adap->dev, "No i2c address for %pOF\n", node); return 0xffffffff; } @@ -315,8 +315,7 @@ static bool i2c_powermac_get_type(struct i2c_adapter *adap, } } - dev_err(&adap->dev, "i2c-powermac: modalias failure" - " on %s\n", node->full_name); + dev_err(&adap->dev, "i2c-powermac: modalias failure on %pOF\n", node); return false; } @@ -348,8 +347,7 @@ static void i2c_powermac_register_devices(struct i2c_adapter *adap, if (!pmac_i2c_match_adapter(node, adap)) continue; - dev_dbg(&adap->dev, "i2c-powermac: register %s\n", - node->full_name); + dev_dbg(&adap->dev, "i2c-powermac: register %pOF\n", node); /* * Keep track of some device existence to handle @@ -372,7 +370,7 @@ static void i2c_powermac_register_devices(struct i2c_adapter *adap, newdev = i2c_new_device(adap, &info); if (!newdev) { dev_err(&adap->dev, "i2c-powermac: Failure to register" - " %s\n", node->full_name); + " %pOF\n", node); of_node_put(node); /* We do not dispose of the interrupt mapping on * purpose. It's not necessary (interrupt cannot be diff --git a/drivers/i2c/busses/i2c-sun6i-p2wi.c b/drivers/i2c/busses/i2c-sun6i-p2wi.c index 7668e2e9b8fd..8a24464dc337 100644 --- a/drivers/i2c/busses/i2c-sun6i-p2wi.c +++ b/drivers/i2c/busses/i2c-sun6i-p2wi.c @@ -223,8 +223,8 @@ static int p2wi_probe(struct platform_device *pdev) if (childnp) { ret = of_property_read_u32(childnp, "reg", &slave_addr); if (ret) { - dev_err(dev, "invalid slave address on node %s\n", - childnp->full_name); + dev_err(dev, "invalid slave address on node %pOF\n", + childnp); return -EINVAL; } diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c index ccf82fdbcd8e..8d474bb1dc15 100644 --- a/drivers/i2c/i2c-core-of.c +++ b/drivers/i2c/i2c-core-of.c @@ -32,18 +32,17 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, u32 addr; int len; - dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name); + dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node); if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) { - dev_err(&adap->dev, "of_i2c: modalias failure on %s\n", - node->full_name); + dev_err(&adap->dev, "of_i2c: modalias failure on %pOF\n", + node); return ERR_PTR(-EINVAL); } addr_be = of_get_property(node, "reg", &len); if (!addr_be || (len < sizeof(*addr_be))) { - dev_err(&adap->dev, "of_i2c: invalid reg on %s\n", - node->full_name); + dev_err(&adap->dev, "of_i2c: invalid reg on %pOF\n", node); return ERR_PTR(-EINVAL); } @@ -59,8 +58,8 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, } if (i2c_check_addr_validity(addr, info.flags)) { - dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n", - addr, node->full_name); + dev_err(&adap->dev, "of_i2c: invalid addr=%x on %pOF\n", + addr, node); return ERR_PTR(-EINVAL); } @@ -76,8 +75,7 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, result = i2c_new_device(adap, &info); if (result == NULL) { - dev_err(&adap->dev, "of_i2c: Failure registering %s\n", - node->full_name); + dev_err(&adap->dev, "of_i2c: Failure registering %pOF\n", node); of_node_put(node); return ERR_PTR(-EINVAL); } @@ -106,8 +104,8 @@ void of_i2c_register_devices(struct i2c_adapter *adap) client = of_i2c_register_device(adap, node); if (IS_ERR(client)) { dev_warn(&adap->dev, - "Failed to create I2C device for %s\n", - node->full_name); + "Failed to create I2C device for %pOF\n", + node); of_node_clear_flag(node, OF_POPULATED); } } @@ -243,8 +241,8 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action, put_device(&adap->dev); if (IS_ERR(client)) { - dev_err(&adap->dev, "failed to create client for '%s'\n", - rd->dn->full_name); + dev_err(&adap->dev, "failed to create client for '%pOF'\n", + rd->dn); of_node_clear_flag(rd->dn, OF_POPULATED); return notifier_from_errno(PTR_ERR(client)); } diff --git a/drivers/i2c/muxes/i2c-demux-pinctrl.c b/drivers/i2c/muxes/i2c-demux-pinctrl.c index 3e6fe1760d82..33ce032cb701 100644 --- a/drivers/i2c/muxes/i2c-demux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-demux-pinctrl.c @@ -167,8 +167,8 @@ static ssize_t available_masters_show(struct device *dev, int count = 0, i; for (i = 0; i < priv->num_chan && count < PAGE_SIZE; i++) - count += scnprintf(buf + count, PAGE_SIZE - count, "%d:%s%c", - i, priv->chan[i].parent_np->full_name, + count += scnprintf(buf + count, PAGE_SIZE - count, "%d:%pOF%c", + i, priv->chan[i].parent_np, i == priv->num_chan - 1 ? '\n' : ' '); return count; -- cgit v1.2.3 From 8dc0f8c73c54c9d1a7fe8188ef3e70123a960eaf Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 9 Jul 2017 15:57:44 -0500 Subject: i2c: constify internal structures Check for i2c_algorithm and i2c_adapter_quirks structures that are only stored in the algo and quirks fields of an i2c_adapter structure correspondingly. These fields are declared const, so i2c_algorithm and i2c_adapter_quirks structures that have this property can be declared as const also. Signed-off-by: Gustavo A. R. Silva Acked-by: Andy Shevchenko (for designware) Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-davinci.c | 2 +- drivers/i2c/busses/i2c-designware-slave.c | 2 +- drivers/i2c/busses/i2c-pmcmsp.c | 4 ++-- drivers/i2c/busses/i2c-stm32f4.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 9163a1c9bddc..33ca9a336182 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -733,7 +733,7 @@ static inline void i2c_davinci_cpufreq_deregister(struct davinci_i2c_dev *dev) } #endif -static struct i2c_algorithm i2c_davinci_algo = { +static const struct i2c_algorithm i2c_davinci_algo = { .master_xfer = i2c_davinci_xfer, .functionality = i2c_davinci_func, }; diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c index 0548c7ea578c..60a79770a1f6 100644 --- a/drivers/i2c/busses/i2c-designware-slave.c +++ b/drivers/i2c/busses/i2c-designware-slave.c @@ -343,7 +343,7 @@ static irqreturn_t i2c_dw_isr_slave(int this_irq, void *dev_id) return IRQ_RETVAL(ret); } -static struct i2c_algorithm i2c_dw_algo = { +static const struct i2c_algorithm i2c_dw_algo = { .functionality = i2c_dw_func, .reg_slave = i2c_dw_reg_slave, .unreg_slave = i2c_dw_unreg_slave, diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c index 217c78711d65..2aa0e83174c5 100644 --- a/drivers/i2c/busses/i2c-pmcmsp.c +++ b/drivers/i2c/busses/i2c-pmcmsp.c @@ -577,7 +577,7 @@ static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter) I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL; } -static struct i2c_adapter_quirks pmcmsptwi_i2c_quirks = { +static const struct i2c_adapter_quirks pmcmsptwi_i2c_quirks = { .flags = I2C_AQ_COMB_WRITE_THEN_READ, .max_write_len = MSP_MAX_BYTES_PER_RW, .max_read_len = MSP_MAX_BYTES_PER_RW, @@ -587,7 +587,7 @@ static struct i2c_adapter_quirks pmcmsptwi_i2c_quirks = { /* -- Initialization -- */ -static struct i2c_algorithm pmcmsptwi_algo = { +static const struct i2c_algorithm pmcmsptwi_algo = { .master_xfer = pmcmsptwi_master_xfer, .functionality = pmcmsptwi_i2c_func, }; diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c index f9dd7e86b861..9d6f1103314a 100644 --- a/drivers/i2c/busses/i2c-stm32f4.c +++ b/drivers/i2c/busses/i2c-stm32f4.c @@ -751,7 +751,7 @@ static u32 stm32f4_i2c_func(struct i2c_adapter *adap) return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } -static struct i2c_algorithm stm32f4_i2c_algo = { +static const struct i2c_algorithm stm32f4_i2c_algo = { .master_xfer = stm32f4_i2c_xfer, .functionality = stm32f4_i2c_func, }; -- cgit v1.2.3 From 9f9d6a40108e93b8d913e82cd43eb081885fd9ca Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 31 Jul 2017 14:53:06 +0900 Subject: i2c: uniphier: add suspend / resume support When resuming, set up registers that have been lost in the sleep state. Also, add clock handling in the resume / suspend hooks. Signed-off-by: Masahiro Yamada Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-uniphier.c | 40 ++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c index 777c0fe93653..bb181b088291 100644 --- a/drivers/i2c/busses/i2c-uniphier.c +++ b/drivers/i2c/busses/i2c-uniphier.c @@ -53,6 +53,7 @@ struct uniphier_i2c_priv { void __iomem *membase; struct clk *clk; unsigned int busy_cnt; + unsigned int clk_cycle; }; static irqreturn_t uniphier_i2c_interrupt(int irq, void *dev_id) @@ -316,13 +317,13 @@ static struct i2c_bus_recovery_info uniphier_i2c_bus_recovery_info = { .unprepare_recovery = uniphier_i2c_unprepare_recovery, }; -static void uniphier_i2c_hw_init(struct uniphier_i2c_priv *priv, - u32 bus_speed, unsigned long clk_rate) +static void uniphier_i2c_hw_init(struct uniphier_i2c_priv *priv) { + unsigned int cyc = priv->clk_cycle; + uniphier_i2c_reset(priv, true); - writel((clk_rate / bus_speed / 2 << 16) | (clk_rate / bus_speed), - priv->membase + UNIPHIER_I2C_CLK); + writel((cyc / 2 << 16) | cyc, priv->membase + UNIPHIER_I2C_CLK); uniphier_i2c_reset(priv, false); } @@ -376,6 +377,7 @@ static int uniphier_i2c_probe(struct platform_device *pdev) goto disable_clk; } + priv->clk_cycle = clk_rate / bus_speed; init_completion(&priv->comp); priv->adap.owner = THIS_MODULE; priv->adap.algo = &uniphier_i2c_algo; @@ -386,7 +388,7 @@ static int uniphier_i2c_probe(struct platform_device *pdev) i2c_set_adapdata(&priv->adap, priv); platform_set_drvdata(pdev, priv); - uniphier_i2c_hw_init(priv, bus_speed, clk_rate); + uniphier_i2c_hw_init(priv); ret = devm_request_irq(dev, irq, uniphier_i2c_interrupt, 0, pdev->name, priv); @@ -413,6 +415,33 @@ static int uniphier_i2c_remove(struct platform_device *pdev) return 0; } +static int __maybe_unused uniphier_i2c_suspend(struct device *dev) +{ + struct uniphier_i2c_priv *priv = dev_get_drvdata(dev); + + clk_disable_unprepare(priv->clk); + + return 0; +} + +static int __maybe_unused uniphier_i2c_resume(struct device *dev) +{ + struct uniphier_i2c_priv *priv = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(priv->clk); + if (ret) + return ret; + + uniphier_i2c_hw_init(priv); + + return 0; +} + +static const struct dev_pm_ops uniphier_i2c_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(uniphier_i2c_suspend, uniphier_i2c_resume) +}; + static const struct of_device_id uniphier_i2c_match[] = { { .compatible = "socionext,uniphier-i2c" }, { /* sentinel */ } @@ -425,6 +454,7 @@ static struct platform_driver uniphier_i2c_drv = { .driver = { .name = "uniphier-i2c", .of_match_table = uniphier_i2c_match, + .pm = &uniphier_i2c_pm_ops, }, }; module_platform_driver(uniphier_i2c_drv); -- cgit v1.2.3 From 822c8d45a170312e368271c3c8f43d49cac863a2 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 31 Jul 2017 14:53:07 +0900 Subject: i2c: uniphier-f: add suspend / resume support When resuming, set up registers that have been lost in the sleep state. Also, add clock handling in the resume / suspend hooks. Signed-off-by: Masahiro Yamada Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-uniphier-f.c | 46 +++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c index beee31892295..9918bdd81619 100644 --- a/drivers/i2c/busses/i2c-uniphier-f.c +++ b/drivers/i2c/busses/i2c-uniphier-f.c @@ -97,6 +97,7 @@ struct uniphier_fi2c_priv { int error; unsigned int flags; unsigned int busy_cnt; + unsigned int clk_cycle; }; static void uniphier_fi2c_fill_txfifo(struct uniphier_fi2c_priv *priv, @@ -461,9 +462,9 @@ static struct i2c_bus_recovery_info uniphier_fi2c_bus_recovery_info = { .unprepare_recovery = uniphier_fi2c_unprepare_recovery, }; -static void uniphier_fi2c_hw_init(struct uniphier_fi2c_priv *priv, - u32 bus_speed, unsigned long clk_rate) +static void uniphier_fi2c_hw_init(struct uniphier_fi2c_priv *priv) { + unsigned int cyc = priv->clk_cycle; u32 tmp; tmp = readl(priv->membase + UNIPHIER_FI2C_CR); @@ -472,12 +473,10 @@ static void uniphier_fi2c_hw_init(struct uniphier_fi2c_priv *priv, uniphier_fi2c_reset(priv); - tmp = clk_rate / bus_speed; - - writel(tmp, priv->membase + UNIPHIER_FI2C_CYC); - writel(tmp / 2, priv->membase + UNIPHIER_FI2C_LCTL); - writel(tmp / 2, priv->membase + UNIPHIER_FI2C_SSUT); - writel(tmp / 16, priv->membase + UNIPHIER_FI2C_DSUT); + writel(cyc, priv->membase + UNIPHIER_FI2C_CYC); + writel(cyc / 2, priv->membase + UNIPHIER_FI2C_LCTL); + writel(cyc / 2, priv->membase + UNIPHIER_FI2C_SSUT); + writel(cyc / 16, priv->membase + UNIPHIER_FI2C_DSUT); uniphier_fi2c_prepare_operation(priv); } @@ -531,6 +530,7 @@ static int uniphier_fi2c_probe(struct platform_device *pdev) goto disable_clk; } + priv->clk_cycle = clk_rate / bus_speed; init_completion(&priv->comp); priv->adap.owner = THIS_MODULE; priv->adap.algo = &uniphier_fi2c_algo; @@ -541,7 +541,7 @@ static int uniphier_fi2c_probe(struct platform_device *pdev) i2c_set_adapdata(&priv->adap, priv); platform_set_drvdata(pdev, priv); - uniphier_fi2c_hw_init(priv, bus_speed, clk_rate); + uniphier_fi2c_hw_init(priv); ret = devm_request_irq(dev, irq, uniphier_fi2c_interrupt, 0, pdev->name, priv); @@ -568,6 +568,33 @@ static int uniphier_fi2c_remove(struct platform_device *pdev) return 0; } +static int __maybe_unused uniphier_fi2c_suspend(struct device *dev) +{ + struct uniphier_fi2c_priv *priv = dev_get_drvdata(dev); + + clk_disable_unprepare(priv->clk); + + return 0; +} + +static int __maybe_unused uniphier_fi2c_resume(struct device *dev) +{ + struct uniphier_fi2c_priv *priv = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(priv->clk); + if (ret) + return ret; + + uniphier_fi2c_hw_init(priv); + + return 0; +} + +static const struct dev_pm_ops uniphier_fi2c_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(uniphier_fi2c_suspend, uniphier_fi2c_resume) +}; + static const struct of_device_id uniphier_fi2c_match[] = { { .compatible = "socionext,uniphier-fi2c" }, { /* sentinel */ } @@ -580,6 +607,7 @@ static struct platform_driver uniphier_fi2c_drv = { .driver = { .name = "uniphier-fi2c", .of_match_table = uniphier_fi2c_match, + .pm = &uniphier_fi2c_pm_ops, }, }; module_platform_driver(uniphier_fi2c_drv); -- cgit v1.2.3 From f14cb3e277f8fb87ef7e4bb1b81e53eafe3ec3ba Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Fri, 11 Aug 2017 11:38:29 +0800 Subject: dt-bindings: i2c: rk3x: add support for rv1108 Add dt Document for i2c controller on rv1108 Signed-off-by: Andy Yan Acked-by: Rob Herring Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-rk3x.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt index e18445d0980c..22f2eeb2c4c9 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-rk3x.txt @@ -7,6 +7,7 @@ Required properties : - reg : Offset and length of the register set for the device - compatible: should be one of the following: + - "rockchip,rv1108-i2c": for rv1108 - "rockchip,rk3066-i2c": for rk3066 - "rockchip,rk3188-i2c": for rk3188 - "rockchip,rk3228-i2c": for rk3228 -- cgit v1.2.3 From 0dbb9634e5355a27f4f25d0ceb3ed4ab2c8d17a5 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Fri, 11 Aug 2017 11:39:13 +0800 Subject: i2c: rk3x: add support for rv1108 Support for the i2c controller on rv1108 soc. Signed-off-by: Andy Yan Reviewed-by: Heiko Stuebner Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-rk3x.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index df220666d627..fe234578380a 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -1131,6 +1131,11 @@ static const struct i2c_algorithm rk3x_i2c_algorithm = { .functionality = rk3x_i2c_func, }; +static const struct rk3x_i2c_soc_data rv1108_soc_data = { + .grf_offset = -1, + .calc_timings = rk3x_i2c_v1_calc_timings, +}; + static const struct rk3x_i2c_soc_data rk3066_soc_data = { .grf_offset = 0x154, .calc_timings = rk3x_i2c_v0_calc_timings, @@ -1157,6 +1162,10 @@ static const struct rk3x_i2c_soc_data rk3399_soc_data = { }; static const struct of_device_id rk3x_i2c_match[] = { + { + .compatible = "rockchip,rv1108-i2c", + .data = (void *)&rv1108_soc_data + }, { .compatible = "rockchip,rk3066-i2c", .data = (void *)&rk3066_soc_data -- cgit v1.2.3 From 4523656ff6cba7a217d44e5e8f726ccca2736473 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Tue, 8 Aug 2017 12:20:31 +0100 Subject: dt-bindings: i2c: Document r8a7743/5 support Document i2c Device Tree support for RZ/G1[ME] (also known as r8aA774[35]) SoCs. They are compatible with R-Car Gen2 SoC family. Signed-off-by: Biju Das Acked-by: Simon Horman Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-rcar.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-rcar.txt b/Documentation/devicetree/bindings/i2c/i2c-rcar.txt index 2b8bd33dbf8d..cad39aee9f73 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-rcar.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-rcar.txt @@ -2,6 +2,8 @@ I2C for R-Car platforms Required properties: - compatible: + "renesas,i2c-r8a7743" if the device is a part of a R8A7743 SoC. + "renesas,i2c-r8a7745" if the device is a part of a R8A7745 SoC. "renesas,i2c-r8a7778" if the device is a part of a R8A7778 SoC. "renesas,i2c-r8a7779" if the device is a part of a R8A7779 SoC. "renesas,i2c-r8a7790" if the device is a part of a R8A7790 SoC. @@ -12,7 +14,8 @@ Required properties: "renesas,i2c-r8a7795" if the device is a part of a R8A7795 SoC. "renesas,i2c-r8a7796" if the device is a part of a R8A7796 SoC. "renesas,rcar-gen1-i2c" for a generic R-Car Gen1 compatible device. - "renesas,rcar-gen2-i2c" for a generic R-Car Gen2 compatible device. + "renesas,rcar-gen2-i2c" for a generic R-Car Gen2 or RZ/G1 compatible + device. "renesas,rcar-gen3-i2c" for a generic R-Car Gen3 compatible device. "renesas,i2c-rcar" (deprecated) -- cgit v1.2.3 From 6c448f04c83713c49be7baf341ed6a04d7493a15 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Tue, 8 Aug 2017 13:45:49 +0100 Subject: dt-bindings: i2c: sh_mobile: Document r8a7743/5 support Document i2c Device Tree support for RZ/G1[ME] (also known as r8a774[35]) SoCs. They are compatible with R-Car Gen2 SoC family. No driver change is required as the initialisation sequence is currently the same as for the R-Car Gen2 fallback binding. Signed-off-by: Biju Das Acked-by: Simon Horman Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt b/Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt index ae9c2a735f39..224390999e81 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt @@ -4,6 +4,8 @@ Required properties: - compatible : - "renesas,iic-r8a73a4" (R-Mobile APE6) - "renesas,iic-r8a7740" (R-Mobile A1) + - "renesas,iic-r8a7743" (RZ/G1M) + - "renesas,iic-r8a7745" (RZ/G1E) - "renesas,iic-r8a7790" (R-Car H2) - "renesas,iic-r8a7791" (R-Car M2-W) - "renesas,iic-r8a7792" (R-Car V2H) @@ -12,7 +14,8 @@ Required properties: - "renesas,iic-r8a7795" (R-Car H3) - "renesas,iic-r8a7796" (R-Car M3-W) - "renesas,iic-sh73a0" (SH-Mobile AG5) - - "renesas,rcar-gen2-iic" (generic R-Car Gen2 compatible device) + - "renesas,rcar-gen2-iic" (generic R-Car Gen2 or RZ/G1 + compatible device) - "renesas,rcar-gen3-iic" (generic R-Car Gen3 compatible device) - "renesas,rmobile-iic" (generic device) -- cgit v1.2.3 From 0a1c7959acd9674a0e4e59f911f3e5fbf25fd693 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 17 May 2017 17:22:18 +0200 Subject: gpu: drm: tc35876x: move header file out of I2C realm include/linux/i2c is not for client devices. Move the header file to a more appropriate location. Signed-off-by: Wolfram Sang Acked-by: Patrik Jakobsson --- arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c | 2 +- drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c | 2 +- include/linux/i2c/tc35876x.h | 11 ----------- include/linux/platform_data/tc35876x.h | 11 +++++++++++ 4 files changed, 13 insertions(+), 13 deletions(-) delete mode 100644 include/linux/i2c/tc35876x.h create mode 100644 include/linux/platform_data/tc35876x.h diff --git a/arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c b/arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c index b1526b95fd43..2905376559f1 100644 --- a/arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c +++ b/arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c @@ -11,7 +11,7 @@ */ #include -#include +#include #include /*tc35876x DSI_LVDS bridge chip and panel platform data*/ diff --git a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c b/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c index 771ff66711af..37c997e24b9e 100644 --- a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c +++ b/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c @@ -26,7 +26,7 @@ #include "mdfld_output.h" #include "mdfld_dsi_pkg_sender.h" #include "tc35876x-dsi-lvds.h" -#include +#include #include #include #include diff --git a/include/linux/i2c/tc35876x.h b/include/linux/i2c/tc35876x.h deleted file mode 100644 index cd6a51c71e7e..000000000000 --- a/include/linux/i2c/tc35876x.h +++ /dev/null @@ -1,11 +0,0 @@ - -#ifndef _TC35876X_H -#define _TC35876X_H - -struct tc35876x_platform_data { - int gpio_bridge_reset; - int gpio_panel_bl_en; - int gpio_panel_vadd; -}; - -#endif /* _TC35876X_H */ diff --git a/include/linux/platform_data/tc35876x.h b/include/linux/platform_data/tc35876x.h new file mode 100644 index 000000000000..cd6a51c71e7e --- /dev/null +++ b/include/linux/platform_data/tc35876x.h @@ -0,0 +1,11 @@ + +#ifndef _TC35876X_H +#define _TC35876X_H + +struct tc35876x_platform_data { + int gpio_bridge_reset; + int gpio_panel_bl_en; + int gpio_panel_vadd; +}; + +#endif /* _TC35876X_H */ -- cgit v1.2.3 From 17a924bfe0af0f74625c19a41807e963a4f06936 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 13 Aug 2017 12:16:51 +0200 Subject: i2c-cht-wc: Add Intel Cherry Trail Whiskey Cove SMBUS controller driver The Intel Cherry Trail Whiskey Cove PMIC does not contain a builtin battery charger, instead boards with this PMIC use an external TI bq24292i charger IC, which is connected to a SMBUS controller built into the PMIC. This commit adds an i2c-bus driver for the PMIC's builtin SMBUS controller. The probe function for this i2c-bus will also register an i2c-client for the TI bq24292i charger after the i2c-bus has been registered. Note that several device-properties are set on the client-device to tell the bq24190 power-supply driver to integrate the Whiskey Cove PMIC and e.g. use the PMIC's BC1.2 detection (through extcon) to determine the maximum input current. Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Kconfig | 8 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-cht-wc.c | 337 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 346 insertions(+) create mode 100644 drivers/i2c/busses/i2c-cht-wc.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 1006b230b236..f20b1f84013a 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -189,6 +189,14 @@ config I2C_PIIX4 This driver can also be built as a module. If so, the module will be called i2c-piix4. +config I2C_CHT_WC + tristate "Intel Cherry Trail Whiskey Cove PMIC smbus controller" + depends on INTEL_SOC_PMIC_CHTWC + help + If you say yes to this option, support will be included for the + SMBus controller found in the Intel Cherry Trail Whiskey Cove PMIC + found on some Intel Cherry Trail systems. + config I2C_NFORCE2 tristate "Nvidia nForce2, nForce3 and nForce4" depends on PCI diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 1b2fc815a4d8..4e654b5dbe6f 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o +obj-$(CONFIG_I2C_CHT_WC) += i2c-cht-wc.o obj-$(CONFIG_I2C_I801) += i2c-i801.o obj-$(CONFIG_I2C_ISCH) += i2c-isch.o obj-$(CONFIG_I2C_ISMT) += i2c-ismt.o diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c new file mode 100644 index 000000000000..fe5caf70c7fe --- /dev/null +++ b/drivers/i2c/busses/i2c-cht-wc.c @@ -0,0 +1,337 @@ +/* + * Intel CHT Whiskey Cove PMIC I2C Master driver + * Copyright (C) 2017 Hans de Goede + * + * Based on various non upstream patches to support the CHT Whiskey Cove PMIC: + * Copyright (C) 2011 - 2014 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CHT_WC_I2C_CTRL 0x5e24 +#define CHT_WC_I2C_CTRL_WR BIT(0) +#define CHT_WC_I2C_CTRL_RD BIT(1) +#define CHT_WC_I2C_CLIENT_ADDR 0x5e25 +#define CHT_WC_I2C_REG_OFFSET 0x5e26 +#define CHT_WC_I2C_WRDATA 0x5e27 +#define CHT_WC_I2C_RDDATA 0x5e28 + +#define CHT_WC_EXTCHGRIRQ 0x6e0a +#define CHT_WC_EXTCHGRIRQ_CLIENT_IRQ BIT(0) +#define CHT_WC_EXTCHGRIRQ_WRITE_IRQ BIT(1) +#define CHT_WC_EXTCHGRIRQ_READ_IRQ BIT(2) +#define CHT_WC_EXTCHGRIRQ_NACK_IRQ BIT(3) +#define CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK ((u8)GENMASK(3, 1)) +#define CHT_WC_EXTCHGRIRQ_MSK 0x6e17 + +struct cht_wc_i2c_adap { + struct i2c_adapter adapter; + wait_queue_head_t wait; + struct irq_chip irqchip; + struct mutex irqchip_lock; + struct regmap *regmap; + struct irq_domain *irq_domain; + struct i2c_client *client; + int client_irq; + u8 irq_mask; + u8 old_irq_mask; + bool nack; + bool done; +}; + +static irqreturn_t cht_wc_i2c_adap_thread_handler(int id, void *data) +{ + struct cht_wc_i2c_adap *adap = data; + int ret, reg; + + /* Read IRQs */ + ret = regmap_read(adap->regmap, CHT_WC_EXTCHGRIRQ, ®); + if (ret) { + dev_err(&adap->adapter.dev, "Error reading extchgrirq reg\n"); + return IRQ_NONE; + } + + reg &= ~adap->irq_mask; + + /* + * Immediately ack IRQs, so that if new IRQs arrives while we're + * handling the previous ones our irq will re-trigger when we're done. + */ + ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, reg); + if (ret) + dev_err(&adap->adapter.dev, "Error writing extchgrirq reg\n"); + + /* + * Do NOT use handle_nested_irq here, the client irq handler will + * likely want to do i2c transfers and the i2c controller uses this + * interrupt handler as well, so running the client irq handler from + * this thread will cause things to lock up. + */ + if (reg & CHT_WC_EXTCHGRIRQ_CLIENT_IRQ) { + /* + * generic_handle_irq expects local IRQs to be disabled + * as normally it is called from interrupt context. + */ + local_irq_disable(); + generic_handle_irq(adap->client_irq); + local_irq_enable(); + } + + if (reg & CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK) { + adap->nack = !!(reg & CHT_WC_EXTCHGRIRQ_NACK_IRQ); + adap->done = true; + wake_up(&adap->wait); + } + + return IRQ_HANDLED; +} + +static u32 cht_wc_i2c_adap_master_func(struct i2c_adapter *adap) +{ + /* This i2c adapter only supports SMBUS byte transfers */ + return I2C_FUNC_SMBUS_BYTE_DATA; +} + +static int cht_wc_i2c_adap_smbus_xfer(struct i2c_adapter *_adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, + union i2c_smbus_data *data) +{ + struct cht_wc_i2c_adap *adap = i2c_get_adapdata(_adap); + int ret, reg; + + adap->nack = false; + adap->done = false; + + ret = regmap_write(adap->regmap, CHT_WC_I2C_CLIENT_ADDR, addr); + if (ret) + return ret; + + if (read_write == I2C_SMBUS_WRITE) { + ret = regmap_write(adap->regmap, CHT_WC_I2C_WRDATA, data->byte); + if (ret) + return ret; + } + + ret = regmap_write(adap->regmap, CHT_WC_I2C_REG_OFFSET, command); + if (ret) + return ret; + + ret = regmap_write(adap->regmap, CHT_WC_I2C_CTRL, + (read_write == I2C_SMBUS_WRITE) ? + CHT_WC_I2C_CTRL_WR : CHT_WC_I2C_CTRL_RD); + if (ret) + return ret; + + /* 3 second timeout, during cable plug the PMIC responds quite slow */ + ret = wait_event_timeout(adap->wait, adap->done, 3 * HZ); + if (ret == 0) + return -ETIMEDOUT; + if (adap->nack) + return -EIO; + + if (read_write == I2C_SMBUS_READ) { + ret = regmap_read(adap->regmap, CHT_WC_I2C_RDDATA, ®); + if (ret) + return ret; + + data->byte = reg; + } + + return 0; +} + +static const struct i2c_algorithm cht_wc_i2c_adap_algo = { + .functionality = cht_wc_i2c_adap_master_func, + .smbus_xfer = cht_wc_i2c_adap_smbus_xfer, +}; + +/**** irqchip for the client connected to the extchgr i2c adapter ****/ +static void cht_wc_i2c_irq_lock(struct irq_data *data) +{ + struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data); + + mutex_lock(&adap->irqchip_lock); +} + +static void cht_wc_i2c_irq_sync_unlock(struct irq_data *data) +{ + struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data); + int ret; + + if (adap->irq_mask != adap->old_irq_mask) { + ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ_MSK, + adap->irq_mask); + if (ret == 0) + adap->old_irq_mask = adap->irq_mask; + else + dev_err(&adap->adapter.dev, "Error writing EXTCHGRIRQ_MSK\n"); + } + + mutex_unlock(&adap->irqchip_lock); +} + +static void cht_wc_i2c_irq_enable(struct irq_data *data) +{ + struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data); + + adap->irq_mask &= ~CHT_WC_EXTCHGRIRQ_CLIENT_IRQ; +} + +static void cht_wc_i2c_irq_disable(struct irq_data *data) +{ + struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data); + + adap->irq_mask |= CHT_WC_EXTCHGRIRQ_CLIENT_IRQ; +} + +static const struct irq_chip cht_wc_i2c_irq_chip = { + .irq_bus_lock = cht_wc_i2c_irq_lock, + .irq_bus_sync_unlock = cht_wc_i2c_irq_sync_unlock, + .irq_disable = cht_wc_i2c_irq_disable, + .irq_enable = cht_wc_i2c_irq_enable, + .name = "cht_wc_ext_chrg_irq_chip", +}; + +static const struct property_entry bq24190_props[] = { + PROPERTY_ENTRY_STRING("extcon-name", "cht_wcove_pwrsrc"), + PROPERTY_ENTRY_BOOL("omit-battery-class"), + PROPERTY_ENTRY_BOOL("disable-reset"), + { } +}; + +static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev) +{ + struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent); + struct cht_wc_i2c_adap *adap; + struct i2c_board_info board_info = { + .type = "bq24190", + .addr = 0x6b, + .properties = bq24190_props, + }; + int ret, irq; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "Error missing irq resource\n"); + return -EINVAL; + } + + adap = devm_kzalloc(&pdev->dev, sizeof(*adap), GFP_KERNEL); + if (!adap) + return -ENOMEM; + + init_waitqueue_head(&adap->wait); + mutex_init(&adap->irqchip_lock); + adap->irqchip = cht_wc_i2c_irq_chip; + adap->regmap = pmic->regmap; + adap->adapter.owner = THIS_MODULE; + adap->adapter.class = I2C_CLASS_HWMON; + adap->adapter.algo = &cht_wc_i2c_adap_algo; + strlcpy(adap->adapter.name, "PMIC I2C Adapter", + sizeof(adap->adapter.name)); + adap->adapter.dev.parent = &pdev->dev; + + /* Clear and activate i2c-adapter interrupts, disable client IRQ */ + adap->old_irq_mask = adap->irq_mask = ~CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK; + ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, ~adap->irq_mask); + if (ret) + return ret; + + ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ_MSK, adap->irq_mask); + if (ret) + return ret; + + /* Alloc and register client IRQ */ + adap->irq_domain = irq_domain_add_linear(pdev->dev.of_node, 1, + &irq_domain_simple_ops, NULL); + if (!adap->irq_domain) + return -ENOMEM; + + adap->client_irq = irq_create_mapping(adap->irq_domain, 0); + if (!adap->client_irq) { + ret = -ENOMEM; + goto remove_irq_domain; + } + + irq_set_chip_data(adap->client_irq, adap); + irq_set_chip_and_handler(adap->client_irq, &adap->irqchip, + handle_simple_irq); + + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, + cht_wc_i2c_adap_thread_handler, + IRQF_ONESHOT, "PMIC I2C Adapter", adap); + if (ret) + goto remove_irq_domain; + + i2c_set_adapdata(&adap->adapter, adap); + ret = i2c_add_adapter(&adap->adapter); + if (ret) + goto remove_irq_domain; + + board_info.irq = adap->client_irq; + adap->client = i2c_new_device(&adap->adapter, &board_info); + if (!adap->client) { + ret = -ENOMEM; + goto del_adapter; + } + + platform_set_drvdata(pdev, adap); + return 0; + +del_adapter: + i2c_del_adapter(&adap->adapter); +remove_irq_domain: + irq_domain_remove(adap->irq_domain); + return ret; +} + +static int cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev) +{ + struct cht_wc_i2c_adap *adap = platform_get_drvdata(pdev); + + i2c_unregister_device(adap->client); + i2c_del_adapter(&adap->adapter); + irq_domain_remove(adap->irq_domain); + + return 0; +} + +static struct platform_device_id cht_wc_i2c_adap_id_table[] = { + { .name = "cht_wcove_ext_chgr" }, + {}, +}; +MODULE_DEVICE_TABLE(platform, cht_wc_i2c_adap_id_table); + +struct platform_driver cht_wc_i2c_adap_driver = { + .probe = cht_wc_i2c_adap_i2c_probe, + .remove = cht_wc_i2c_adap_i2c_remove, + .driver = { + .name = "cht_wcove_ext_chgr", + }, + .id_table = cht_wc_i2c_adap_id_table, +}; +module_platform_driver(cht_wc_i2c_adap_driver); + +MODULE_DESCRIPTION("Intel CHT Whiskey Cove PMIC I2C Master driver"); +MODULE_AUTHOR("Hans de Goede "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 885e42d9c267d23d6001275e819e2448bf59ea8c Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 14 Aug 2017 10:23:24 +0200 Subject: i2c: mux: pca9541: sort include files Make it consistent with the other drivers. Signed-off-by: Wolfram Sang Signed-off-by: Peter Rosin --- drivers/i2c/muxes/i2c-mux-pca9541.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c index 9e318c9516c7..be961f2855c7 100644 --- a/drivers/i2c/muxes/i2c-mux-pca9541.c +++ b/drivers/i2c/muxes/i2c-mux-pca9541.c @@ -16,15 +16,14 @@ * warranty of any kind, whether express or implied. */ -#include -#include #include -#include #include #include #include - #include +#include +#include +#include /* * The PCA9541 is a bus master selector. It supports two I2C masters connected -- cgit v1.2.3 From 2be03aedbb6d78929c9e3be0d1850830303744f7 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 14 Aug 2017 10:23:25 +0200 Subject: i2c: mux: pca954x: move header file out of I2C realm include/linux/i2c is not for client devices. Move the header file to a more appropriate location. Signed-off-by: Wolfram Sang Signed-off-by: Peter Rosin --- drivers/i2c/muxes/i2c-mux-pca9541.c | 2 +- drivers/i2c/muxes/i2c-mux-pca954x.c | 2 +- include/linux/i2c/pca954x.h | 48 ----------------------------------- include/linux/platform_data/pca954x.h | 48 +++++++++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 50 deletions(-) delete mode 100644 include/linux/i2c/pca954x.h create mode 100644 include/linux/platform_data/pca954x.h diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c index be961f2855c7..6a39adaf433f 100644 --- a/drivers/i2c/muxes/i2c-mux-pca9541.c +++ b/drivers/i2c/muxes/i2c-mux-pca9541.c @@ -20,9 +20,9 @@ #include #include #include -#include #include #include +#include #include /* diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index f1751c290af6..7b992db38021 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -39,13 +39,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include #include #include diff --git a/include/linux/i2c/pca954x.h b/include/linux/i2c/pca954x.h deleted file mode 100644 index 1712677d5904..000000000000 --- a/include/linux/i2c/pca954x.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * pca954x.h - I2C multiplexer/switch support - * - * Copyright (c) 2008-2009 Rodolfo Giometti - * Copyright (c) 2008-2009 Eurotech S.p.A. - * Michael Lawnick - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#ifndef _LINUX_I2C_PCA954X_H -#define _LINUX_I2C_PCA954X_H - -/* Platform data for the PCA954x I2C multiplexers */ - -/* Per channel initialisation data: - * @adap_id: bus number for the adapter. 0 = don't care - * @deselect_on_exit: set this entry to 1, if your H/W needs deselection - * of this channel after transaction. - * - */ -struct pca954x_platform_mode { - int adap_id; - unsigned int deselect_on_exit:1; - unsigned int class; -}; - -/* Per mux/switch data, used with i2c_register_board_info */ -struct pca954x_platform_data { - struct pca954x_platform_mode *modes; - int num_modes; -}; - -#endif /* _LINUX_I2C_PCA954X_H */ diff --git a/include/linux/platform_data/pca954x.h b/include/linux/platform_data/pca954x.h new file mode 100644 index 000000000000..1712677d5904 --- /dev/null +++ b/include/linux/platform_data/pca954x.h @@ -0,0 +1,48 @@ +/* + * + * pca954x.h - I2C multiplexer/switch support + * + * Copyright (c) 2008-2009 Rodolfo Giometti + * Copyright (c) 2008-2009 Eurotech S.p.A. + * Michael Lawnick + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef _LINUX_I2C_PCA954X_H +#define _LINUX_I2C_PCA954X_H + +/* Platform data for the PCA954x I2C multiplexers */ + +/* Per channel initialisation data: + * @adap_id: bus number for the adapter. 0 = don't care + * @deselect_on_exit: set this entry to 1, if your H/W needs deselection + * of this channel after transaction. + * + */ +struct pca954x_platform_mode { + int adap_id; + unsigned int deselect_on_exit:1; + unsigned int class; +}; + +/* Per mux/switch data, used with i2c_register_board_info */ +struct pca954x_platform_data { + struct pca954x_platform_mode *modes; + int num_modes; +}; + +#endif /* _LINUX_I2C_PCA954X_H */ -- cgit v1.2.3 From 26b1083b4545ec08a7dcfe759323a2e142d60d75 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 14 Aug 2017 10:23:26 +0200 Subject: i2c: mux: mlxcpld: move header file out of I2C realm include/linux/i2c is not for client devices. Move the header file to a more appropriate location. Signed-off-by: Wolfram Sang Signed-off-by: Peter Rosin --- drivers/i2c/muxes/i2c-mux-mlxcpld.c | 2 +- include/linux/i2c/mlxcpld.h | 52 ------------------------------- include/linux/platform_data/x86/mlxcpld.h | 52 +++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 53 deletions(-) delete mode 100644 include/linux/i2c/mlxcpld.h create mode 100644 include/linux/platform_data/x86/mlxcpld.h diff --git a/drivers/i2c/muxes/i2c-mux-mlxcpld.c b/drivers/i2c/muxes/i2c-mux-mlxcpld.c index e53f2abd1350..12ad8d65faf6 100644 --- a/drivers/i2c/muxes/i2c-mux-mlxcpld.c +++ b/drivers/i2c/muxes/i2c-mux-mlxcpld.c @@ -38,9 +38,9 @@ #include #include #include +#include #include #include -#include #define CPLD_MUX_MAX_NCHANS 8 diff --git a/include/linux/i2c/mlxcpld.h b/include/linux/i2c/mlxcpld.h deleted file mode 100644 index b08dcb183fca..000000000000 --- a/include/linux/i2c/mlxcpld.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * mlxcpld.h - Mellanox I2C multiplexer support in CPLD - * - * Copyright (c) 2016 Mellanox Technologies. All rights reserved. - * Copyright (c) 2016 Michael Shych - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the names of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _LINUX_I2C_MLXCPLD_H -#define _LINUX_I2C_MLXCPLD_H - -/* Platform data for the CPLD I2C multiplexers */ - -/* mlxcpld_mux_plat_data - per mux data, used with i2c_register_board_info - * @adap_ids - adapter array - * @num_adaps - number of adapters - * @sel_reg_addr - mux select register offset in CPLD space - */ -struct mlxcpld_mux_plat_data { - int *adap_ids; - int num_adaps; - int sel_reg_addr; -}; - -#endif /* _LINUX_I2C_MLXCPLD_H */ diff --git a/include/linux/platform_data/x86/mlxcpld.h b/include/linux/platform_data/x86/mlxcpld.h new file mode 100644 index 000000000000..b08dcb183fca --- /dev/null +++ b/include/linux/platform_data/x86/mlxcpld.h @@ -0,0 +1,52 @@ +/* + * mlxcpld.h - Mellanox I2C multiplexer support in CPLD + * + * Copyright (c) 2016 Mellanox Technologies. All rights reserved. + * Copyright (c) 2016 Michael Shych + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the names of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINUX_I2C_MLXCPLD_H +#define _LINUX_I2C_MLXCPLD_H + +/* Platform data for the CPLD I2C multiplexers */ + +/* mlxcpld_mux_plat_data - per mux data, used with i2c_register_board_info + * @adap_ids - adapter array + * @num_adaps - number of adapters + * @sel_reg_addr - mux select register offset in CPLD space + */ +struct mlxcpld_mux_plat_data { + int *adap_ids; + int num_adaps; + int sel_reg_addr; +}; + +#endif /* _LINUX_I2C_MLXCPLD_H */ -- cgit v1.2.3 From c4aee3e1b0de8e732fafd0d13e75ab7bdbc606ef Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Sun, 21 May 2017 18:48:07 +0200 Subject: i2c: mux: pinctrl: remove platform_data No platform (at least no upstreamed platform) has ever used this platform_data. Just drop it and simplify the code. Reviewed-by: Stephen Warren Acked-by: Wolfram Sang Signed-off-by: Peter Rosin --- drivers/i2c/muxes/Kconfig | 1 + drivers/i2c/muxes/i2c-mux-pinctrl.c | 219 ++++++++++++------------------------ include/linux/i2c-mux-pinctrl.h | 41 ------- 3 files changed, 72 insertions(+), 189 deletions(-) delete mode 100644 include/linux/i2c-mux-pinctrl.h diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig index 2c64d0e0740f..1bba95ecc7c0 100644 --- a/drivers/i2c/muxes/Kconfig +++ b/drivers/i2c/muxes/Kconfig @@ -76,6 +76,7 @@ config I2C_MUX_PCA954x config I2C_MUX_PINCTRL tristate "pinctrl-based I2C multiplexer" depends on PINCTRL + depends on OF || COMPILE_TEST help If you say yes to this option, support will be included for an I2C multiplexer that uses the pinctrl subsystem, i.e. pin multiplexing. diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index 7c0c264b07bc..aa4a3bf9507f 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -20,14 +20,12 @@ #include #include #include -#include #include #include #include #include "../../pinctrl/core.h" struct i2c_mux_pinctrl { - struct i2c_mux_pinctrl_platform_data *pdata; struct pinctrl *pinctrl; struct pinctrl_state **states; struct pinctrl_state *state_idle; @@ -47,80 +45,6 @@ static int i2c_mux_pinctrl_deselect(struct i2c_mux_core *muxc, u32 chan) return pinctrl_select_state(mux->pinctrl, mux->state_idle); } -#ifdef CONFIG_OF -static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux, - struct platform_device *pdev) -{ - struct device_node *np = pdev->dev.of_node; - int num_names, i, ret; - struct device_node *adapter_np; - struct i2c_adapter *adapter; - - if (!np) - return 0; - - mux->pdata = devm_kzalloc(&pdev->dev, sizeof(*mux->pdata), GFP_KERNEL); - if (!mux->pdata) - return -ENOMEM; - - num_names = of_property_count_strings(np, "pinctrl-names"); - if (num_names < 0) { - dev_err(&pdev->dev, "Cannot parse pinctrl-names: %d\n", - num_names); - return num_names; - } - - mux->pdata->pinctrl_states = devm_kzalloc(&pdev->dev, - sizeof(*mux->pdata->pinctrl_states) * num_names, - GFP_KERNEL); - if (!mux->pdata->pinctrl_states) - return -ENOMEM; - - for (i = 0; i < num_names; i++) { - ret = of_property_read_string_index(np, "pinctrl-names", i, - &mux->pdata->pinctrl_states[mux->pdata->bus_count]); - if (ret < 0) { - dev_err(&pdev->dev, "Cannot parse pinctrl-names: %d\n", - ret); - return ret; - } - if (!strcmp(mux->pdata->pinctrl_states[mux->pdata->bus_count], - "idle")) { - if (i != num_names - 1) { - dev_err(&pdev->dev, - "idle state must be last\n"); - return -EINVAL; - } - mux->pdata->pinctrl_state_idle = "idle"; - } else { - mux->pdata->bus_count++; - } - } - - adapter_np = of_parse_phandle(np, "i2c-parent", 0); - if (!adapter_np) { - dev_err(&pdev->dev, "Cannot parse i2c-parent\n"); - return -ENODEV; - } - adapter = of_find_i2c_adapter_by_node(adapter_np); - of_node_put(adapter_np); - if (!adapter) { - dev_err(&pdev->dev, "Cannot find parent bus\n"); - return -EPROBE_DEFER; - } - mux->pdata->parent_bus_num = i2c_adapter_id(adapter); - put_device(&adapter->dev); - - return 0; -} -#else -static inline int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux, - struct platform_device *pdev) -{ - return 0; -} -#endif - static struct i2c_adapter *i2c_mux_pinctrl_root_adapter( struct pinctrl_state *state) { @@ -141,110 +65,109 @@ static struct i2c_adapter *i2c_mux_pinctrl_root_adapter( return root; } +static struct i2c_adapter *i2c_mux_pinctrl_parent_adapter(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct device_node *parent_np; + struct i2c_adapter *parent; + + parent_np = of_parse_phandle(np, "i2c-parent", 0); + if (!parent_np) { + dev_err(dev, "Cannot parse i2c-parent\n"); + return ERR_PTR(-ENODEV); + } + parent = of_find_i2c_adapter_by_node(parent_np); + of_node_put(parent_np); + if (!parent) + return ERR_PTR(-EPROBE_DEFER); + + return parent; +} + static int i2c_mux_pinctrl_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; struct i2c_mux_core *muxc; struct i2c_mux_pinctrl *mux; + struct i2c_adapter *parent; struct i2c_adapter *root; - int i, ret; - - mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL); - if (!mux) { - ret = -ENOMEM; - goto err; - } + int num_names, i, ret; + const char *name; - mux->pdata = dev_get_platdata(&pdev->dev); - if (!mux->pdata) { - ret = i2c_mux_pinctrl_parse_dt(mux, pdev); - if (ret < 0) - goto err; - } - if (!mux->pdata) { - dev_err(&pdev->dev, "Missing platform data\n"); - ret = -ENODEV; - goto err; + num_names = of_property_count_strings(np, "pinctrl-names"); + if (num_names < 0) { + dev_err(dev, "Cannot parse pinctrl-names: %d\n", + num_names); + return num_names; } - mux->states = devm_kzalloc(&pdev->dev, - sizeof(*mux->states) * mux->pdata->bus_count, - GFP_KERNEL); - if (!mux->states) { - dev_err(&pdev->dev, "Cannot allocate states\n"); - ret = -ENOMEM; - goto err; - } + parent = i2c_mux_pinctrl_parent_adapter(dev); + if (IS_ERR(parent)) + return PTR_ERR(parent); - muxc = i2c_mux_alloc(NULL, &pdev->dev, mux->pdata->bus_count, 0, 0, - i2c_mux_pinctrl_select, NULL); + muxc = i2c_mux_alloc(parent, dev, num_names, + sizeof(*mux) + num_names * sizeof(*mux->states), + 0, i2c_mux_pinctrl_select, NULL); if (!muxc) { ret = -ENOMEM; - goto err; + goto err_put_parent; } - muxc->priv = mux; + mux = i2c_mux_priv(muxc); + mux->states = (struct pinctrl_state **)(mux + 1); platform_set_drvdata(pdev, muxc); - mux->pinctrl = devm_pinctrl_get(&pdev->dev); + mux->pinctrl = devm_pinctrl_get(dev); if (IS_ERR(mux->pinctrl)) { ret = PTR_ERR(mux->pinctrl); - dev_err(&pdev->dev, "Cannot get pinctrl: %d\n", ret); - goto err; + dev_err(dev, "Cannot get pinctrl: %d\n", ret); + goto err_put_parent; } - for (i = 0; i < mux->pdata->bus_count; i++) { - mux->states[i] = pinctrl_lookup_state(mux->pinctrl, - mux->pdata->pinctrl_states[i]); + + for (i = 0; i < num_names; i++) { + ret = of_property_read_string_index(np, "pinctrl-names", i, + &name); + if (ret < 0) { + dev_err(dev, "Cannot parse pinctrl-names: %d\n", ret); + goto err_put_parent; + } + + mux->states[i] = pinctrl_lookup_state(mux->pinctrl, name); if (IS_ERR(mux->states[i])) { ret = PTR_ERR(mux->states[i]); - dev_err(&pdev->dev, - "Cannot look up pinctrl state %s: %d\n", - mux->pdata->pinctrl_states[i], ret); - goto err; - } - } - if (mux->pdata->pinctrl_state_idle) { - mux->state_idle = pinctrl_lookup_state(mux->pinctrl, - mux->pdata->pinctrl_state_idle); - if (IS_ERR(mux->state_idle)) { - ret = PTR_ERR(mux->state_idle); - dev_err(&pdev->dev, - "Cannot look up pinctrl state %s: %d\n", - mux->pdata->pinctrl_state_idle, ret); - goto err; + dev_err(dev, "Cannot look up pinctrl state %s: %d\n", + name, ret); + goto err_put_parent; } - muxc->deselect = i2c_mux_pinctrl_deselect; - } + if (strcmp(name, "idle")) + continue; - muxc->parent = i2c_get_adapter(mux->pdata->parent_bus_num); - if (!muxc->parent) { - dev_err(&pdev->dev, "Parent adapter (%d) not found\n", - mux->pdata->parent_bus_num); - ret = -EPROBE_DEFER; - goto err; + if (i != num_names - 1) { + dev_err(dev, "idle state must be last\n"); + ret = -EINVAL; + goto err_put_parent; + } + mux->state_idle = mux->states[i]; + muxc->deselect = i2c_mux_pinctrl_deselect; } root = i2c_root_adapter(&muxc->parent->dev); muxc->mux_locked = true; - for (i = 0; i < mux->pdata->bus_count; i++) { + for (i = 0; i < num_names; i++) { if (root != i2c_mux_pinctrl_root_adapter(mux->states[i])) { muxc->mux_locked = false; break; } } - if (muxc->mux_locked && mux->pdata->pinctrl_state_idle && - root != i2c_mux_pinctrl_root_adapter(mux->state_idle)) - muxc->mux_locked = false; - if (muxc->mux_locked) - dev_info(&pdev->dev, "mux-locked i2c mux\n"); + dev_info(dev, "mux-locked i2c mux\n"); - for (i = 0; i < mux->pdata->bus_count; i++) { - u32 bus = mux->pdata->base_bus_num ? - (mux->pdata->base_bus_num + i) : 0; - - ret = i2c_mux_add_adapter(muxc, bus, i, 0); + /* Do not add any adapter for the idle state (if it's there at all). */ + for (i = 0; i < num_names - !!mux->state_idle; i++) { + ret = i2c_mux_add_adapter(muxc, 0, i, 0); if (ret) goto err_del_adapter; } @@ -253,8 +176,9 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) err_del_adapter: i2c_mux_del_adapters(muxc); +err_put_parent: i2c_put_adapter(muxc->parent); -err: + return ret; } @@ -264,16 +188,15 @@ static int i2c_mux_pinctrl_remove(struct platform_device *pdev) i2c_mux_del_adapters(muxc); i2c_put_adapter(muxc->parent); + return 0; } -#ifdef CONFIG_OF static const struct of_device_id i2c_mux_pinctrl_of_match[] = { { .compatible = "i2c-mux-pinctrl", }, {}, }; MODULE_DEVICE_TABLE(of, i2c_mux_pinctrl_of_match); -#endif static struct platform_driver i2c_mux_pinctrl_driver = { .driver = { diff --git a/include/linux/i2c-mux-pinctrl.h b/include/linux/i2c-mux-pinctrl.h deleted file mode 100644 index a65c86429e84..000000000000 --- a/include/linux/i2c-mux-pinctrl.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * i2c-mux-pinctrl platform data - * - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _LINUX_I2C_MUX_PINCTRL_H -#define _LINUX_I2C_MUX_PINCTRL_H - -/** - * struct i2c_mux_pinctrl_platform_data - Platform data for i2c-mux-pinctrl - * @parent_bus_num: Parent I2C bus number - * @base_bus_num: Base I2C bus number for the child busses. 0 for dynamic. - * @bus_count: Number of child busses. Also the number of elements in - * @pinctrl_states - * @pinctrl_states: The names of the pinctrl state to select for each child bus - * @pinctrl_state_idle: The pinctrl state to select when no child bus is being - * accessed. If NULL, the most recently used pinctrl state will be left - * selected. - */ -struct i2c_mux_pinctrl_platform_data { - int parent_bus_num; - int base_bus_num; - int bus_count; - const char **pinctrl_states; - const char *pinctrl_state_idle; -}; - -#endif -- cgit v1.2.3 From fc2046718a1bdccc38d749c4453215891f7a014c Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Sun, 21 May 2017 18:49:03 +0200 Subject: i2c: mux: pinctrl: drop the idle_state member The information is available elsewhere. Reviewed-by: Stephen Warren Signed-off-by: Peter Rosin --- drivers/i2c/muxes/i2c-mux-pinctrl.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index aa4a3bf9507f..20b90a7a1e61 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -28,7 +28,6 @@ struct i2c_mux_pinctrl { struct pinctrl *pinctrl; struct pinctrl_state **states; - struct pinctrl_state *state_idle; }; static int i2c_mux_pinctrl_select(struct i2c_mux_core *muxc, u32 chan) @@ -40,9 +39,7 @@ static int i2c_mux_pinctrl_select(struct i2c_mux_core *muxc, u32 chan) static int i2c_mux_pinctrl_deselect(struct i2c_mux_core *muxc, u32 chan) { - struct i2c_mux_pinctrl *mux = i2c_mux_priv(muxc); - - return pinctrl_select_state(mux->pinctrl, mux->state_idle); + return i2c_mux_pinctrl_select(muxc, muxc->num_adapters); } static struct i2c_adapter *i2c_mux_pinctrl_root_adapter( @@ -149,7 +146,6 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) ret = -EINVAL; goto err_put_parent; } - mux->state_idle = mux->states[i]; muxc->deselect = i2c_mux_pinctrl_deselect; } @@ -166,7 +162,7 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) dev_info(dev, "mux-locked i2c mux\n"); /* Do not add any adapter for the idle state (if it's there at all). */ - for (i = 0; i < num_names - !!mux->state_idle; i++) { + for (i = 0; i < num_names - !!muxc->deselect; i++) { ret = i2c_mux_add_adapter(muxc, 0, i, 0); if (ret) goto err_del_adapter; -- cgit v1.2.3 From 9024ca12ed1067d1d35e4a431cb8f03dcaff0987 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 19 Jul 2017 17:25:31 +0200 Subject: i2c: mv64xxx: explicitly request exclusive reset control Commit a53e35db70d1 ("reset: Ensure drivers are explicit when requesting reset lines") started to transition the reset control request API calls to explicitly state whether the driver needs exclusive or shared reset control behavior. Convert all drivers requesting exclusive resets to the explicit API call so the temporary transition helpers can be removed. No functional changes. Cc: Wolfram Sang Cc: linux-i2c@vger.kernel.org Signed-off-by: Philipp Zabel Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mv64xxx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index b2ef32b188e1..a832c45276a4 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -820,7 +820,7 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, goto out; } - drv_data->rstc = devm_reset_control_get_optional(dev, NULL); + drv_data->rstc = devm_reset_control_get_optional_exclusive(dev, NULL); if (IS_ERR(drv_data->rstc)) { rc = PTR_ERR(drv_data->rstc); goto out; -- cgit v1.2.3 From 961e026a06da0db68295bb012a34c5bcb8388d7c Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 19 Jul 2017 17:25:32 +0200 Subject: i2c: stm32f4: explicitly request exclusive reset control Commit a53e35db70d1 ("reset: Ensure drivers are explicit when requesting reset lines") started to transition the reset control request API calls to explicitly state whether the driver needs exclusive or shared reset control behavior. Convert all drivers requesting exclusive resets to the explicit API call so the temporary transition helpers can be removed. No functional changes. Cc: Wolfram Sang Cc: Maxime Coquelin Cc: Alexandre Torgue Cc: linux-i2c@vger.kernel.org Signed-off-by: Philipp Zabel Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-stm32f4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c index 9d6f1103314a..aceb6f788564 100644 --- a/drivers/i2c/busses/i2c-stm32f4.c +++ b/drivers/i2c/busses/i2c-stm32f4.c @@ -798,7 +798,7 @@ static int stm32f4_i2c_probe(struct platform_device *pdev) return ret; } - rst = devm_reset_control_get(&pdev->dev, NULL); + rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); if (IS_ERR(rst)) { dev_err(&pdev->dev, "Error: Missing controller reset\n"); ret = PTR_ERR(rst); -- cgit v1.2.3 From 96ae9eab03b5d5ba1a427c8bf65d0945a8a287c4 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 19 Jul 2017 17:25:33 +0200 Subject: i2c: sun6i-pw2i: explicitly request exclusive reset control Commit a53e35db70d1 ("reset: Ensure drivers are explicit when requesting reset lines") started to transition the reset control request API calls to explicitly state whether the driver needs exclusive or shared reset control behavior. Convert all drivers requesting exclusive resets to the explicit API call so the temporary transition helpers can be removed. No functional changes. Cc: Wolfram Sang Cc: Maxime Ripard Cc: Chen-Yu Tsai Cc: linux-i2c@vger.kernel.org Signed-off-by: Philipp Zabel Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sun6i-p2wi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-sun6i-p2wi.c b/drivers/i2c/busses/i2c-sun6i-p2wi.c index 8a24464dc337..7c07ce116e38 100644 --- a/drivers/i2c/busses/i2c-sun6i-p2wi.c +++ b/drivers/i2c/busses/i2c-sun6i-p2wi.c @@ -258,7 +258,7 @@ static int p2wi_probe(struct platform_device *pdev) parent_clk_freq = clk_get_rate(p2wi->clk); - p2wi->rstc = devm_reset_control_get(dev, NULL); + p2wi->rstc = devm_reset_control_get_exclusive(dev, NULL); if (IS_ERR(p2wi->rstc)) { ret = PTR_ERR(p2wi->rstc); dev_err(dev, "failed to retrieve reset controller: %d\n", ret); -- cgit v1.2.3 From 94d3b651c0d9ab0023443d8038ef4f4f72c473ec Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 19 Jul 2017 17:25:34 +0200 Subject: i2c: tegra: explicitly request exclusive reset control Commit a53e35db70d1 ("reset: Ensure drivers are explicit when requesting reset lines") started to transition the reset control request API calls to explicitly state whether the driver needs exclusive or shared reset control behavior. Convert all drivers requesting exclusive resets to the explicit API call so the temporary transition helpers can be removed. No functional changes. Cc: Laxman Dewangan Cc: Wolfram Sang Cc: Thierry Reding Cc: Jonathan Hunter Cc: linux-i2c@vger.kernel.org Cc: linux-tegra@vger.kernel.org Signed-off-by: Philipp Zabel Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 4af9bbae20df..a23884445fa2 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -911,7 +911,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) i2c_dev->cont_id = pdev->id; i2c_dev->dev = &pdev->dev; - i2c_dev->rst = devm_reset_control_get(&pdev->dev, "i2c"); + i2c_dev->rst = devm_reset_control_get_exclusive(&pdev->dev, "i2c"); if (IS_ERR(i2c_dev->rst)) { dev_err(&pdev->dev, "missing controller reset\n"); return PTR_ERR(i2c_dev->rst); -- cgit v1.2.3 From 87b59ff8d1d9d809c014a4e20bc043064b6e0047 Mon Sep 17 00:00:00 2001 From: Brendan Higgins Date: Fri, 28 Jul 2017 13:45:58 -0700 Subject: i2c: aspeed: add proper support fo 24xx clock params 24xx BMCs have larger clock divider granularity which can cause problems when trying to set them as 25xx clock dividers; this adds clock setting code specific to 24xx. This also fixes a potential issue where clock dividers were rounded down instead of up. Signed-off-by: Brendan Higgins Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-aspeed.c | 74 +++++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 18 deletions(-) diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index f19348328a71..60afab866494 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -132,6 +132,7 @@ struct aspeed_i2c_bus { /* Synchronizes I/O mem access to base. */ spinlock_t lock; struct completion cmd_complete; + u32 (*get_clk_reg_val)(u32 divisor); unsigned long parent_clk_frequency; u32 bus_frequency; /* Transaction state. */ @@ -674,7 +675,7 @@ static const struct i2c_algorithm aspeed_i2c_algo = { #endif /* CONFIG_I2C_SLAVE */ }; -static u32 aspeed_i2c_get_clk_reg_val(u32 divisor) +static u32 aspeed_i2c_get_clk_reg_val(u32 clk_high_low_max, u32 divisor) { u32 base_clk, clk_high, clk_low, tmp; @@ -694,16 +695,22 @@ static u32 aspeed_i2c_get_clk_reg_val(u32 divisor) * Thus, * SCL_freq = APB_freq / * ((1 << base_clk) * (clk_high + 1 + clk_low + 1)) - * The documentation recommends clk_high >= 8 and clk_low >= 7 when - * possible; this last constraint gives us the following solution: + * The documentation recommends clk_high >= clk_high_max / 2 and + * clk_low >= clk_low_max / 2 - 1 when possible; this last constraint + * gives us the following solution: */ - base_clk = divisor > 33 ? ilog2((divisor - 1) / 32) + 1 : 0; - tmp = divisor / (1 << base_clk); - clk_high = tmp / 2 + tmp % 2; - clk_low = tmp - clk_high; + base_clk = divisor > clk_high_low_max ? + ilog2((divisor - 1) / clk_high_low_max) + 1 : 0; + tmp = (divisor + (1 << base_clk) - 1) >> base_clk; + clk_low = tmp / 2; + clk_high = tmp - clk_low; + + if (clk_high) + clk_high--; + + if (clk_low) + clk_low--; - clk_high -= 1; - clk_low -= 1; return ((clk_high << ASPEED_I2CD_TIME_SCL_HIGH_SHIFT) & ASPEED_I2CD_TIME_SCL_HIGH_MASK) @@ -712,13 +719,31 @@ static u32 aspeed_i2c_get_clk_reg_val(u32 divisor) | (base_clk & ASPEED_I2CD_TIME_BASE_DIVISOR_MASK); } +static u32 aspeed_i2c_24xx_get_clk_reg_val(u32 divisor) +{ + /* + * clk_high and clk_low are each 3 bits wide, so each can hold a max + * value of 8 giving a clk_high_low_max of 16. + */ + return aspeed_i2c_get_clk_reg_val(16, divisor); +} + +static u32 aspeed_i2c_25xx_get_clk_reg_val(u32 divisor) +{ + /* + * clk_high and clk_low are each 4 bits wide, so each can hold a max + * value of 16 giving a clk_high_low_max of 32. + */ + return aspeed_i2c_get_clk_reg_val(32, divisor); +} + /* precondition: bus.lock has been acquired. */ static int aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus) { u32 divisor, clk_reg_val; - divisor = bus->parent_clk_frequency / bus->bus_frequency; - clk_reg_val = aspeed_i2c_get_clk_reg_val(divisor); + divisor = DIV_ROUND_UP(bus->parent_clk_frequency, bus->bus_frequency); + clk_reg_val = bus->get_clk_reg_val(divisor); writel(clk_reg_val, bus->base + ASPEED_I2C_AC_TIMING_REG1); writel(ASPEED_NO_TIMEOUT_CTRL, bus->base + ASPEED_I2C_AC_TIMING_REG2); @@ -777,8 +802,22 @@ static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus) return ret; } +static const struct of_device_id aspeed_i2c_bus_of_table[] = { + { + .compatible = "aspeed,ast2400-i2c-bus", + .data = aspeed_i2c_24xx_get_clk_reg_val, + }, + { + .compatible = "aspeed,ast2500-i2c-bus", + .data = aspeed_i2c_25xx_get_clk_reg_val, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, aspeed_i2c_bus_of_table); + static int aspeed_i2c_probe_bus(struct platform_device *pdev) { + const struct of_device_id *match; struct aspeed_i2c_bus *bus; struct clk *parent_clk; struct resource *res; @@ -808,6 +847,12 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) bus->bus_frequency = 100000; } + match = of_match_node(aspeed_i2c_bus_of_table, pdev->dev.of_node); + if (!match) + bus->get_clk_reg_val = aspeed_i2c_24xx_get_clk_reg_val; + else + bus->get_clk_reg_val = match->data; + /* Initialize the I2C adapter */ spin_lock_init(&bus->lock); init_completion(&bus->cmd_complete); @@ -869,13 +914,6 @@ static int aspeed_i2c_remove_bus(struct platform_device *pdev) return 0; } -static const struct of_device_id aspeed_i2c_bus_of_table[] = { - { .compatible = "aspeed,ast2400-i2c-bus", }, - { .compatible = "aspeed,ast2500-i2c-bus", }, - { }, -}; -MODULE_DEVICE_TABLE(of, aspeed_i2c_bus_of_table); - static struct platform_driver aspeed_i2c_bus_driver = { .probe = aspeed_i2c_probe_bus, .remove = aspeed_i2c_remove_bus, -- cgit v1.2.3 From be9bac020cacd0cdf758b4a6d847a0ba835475b9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 17 Aug 2017 14:53:55 +0300 Subject: i2c: mux: pinctrl: potential NULL dereference on error If i2c_mux_alloc() fails then we'd have a NULL dereference here. Fixes: c4aee3e1b0de ("i2c: mux: pinctrl: remove platform_data") Signed-off-by: Dan Carpenter Signed-off-by: Peter Rosin --- drivers/i2c/muxes/i2c-mux-pinctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index 20b90a7a1e61..cc6818aabab5 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -173,7 +173,7 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) err_del_adapter: i2c_mux_del_adapters(muxc); err_put_parent: - i2c_put_adapter(muxc->parent); + i2c_put_adapter(parent); return ret; } -- cgit v1.2.3 From c6a6bdbdc6cc07257889849d9ddf7256cbf3acbc Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Thu, 17 Aug 2017 17:35:52 +0530 Subject: i2c: taos-evm: constify serio_device_id serio_device_id are not supposed to change at runtime. All functions working with serio_device_id provided by work with const serio_device_id. So mark the non-const structs as const. Signed-off-by: Arvind Yadav Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-taos-evm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c index 210ca82f8aa0..addd90a8cb59 100644 --- a/drivers/i2c/busses/i2c-taos-evm.c +++ b/drivers/i2c/busses/i2c-taos-evm.c @@ -291,7 +291,7 @@ static void taos_disconnect(struct serio *serio) dev_info(&serio->dev, "Disconnected from TAOS EVM\n"); } -static struct serio_device_id taos_serio_ids[] = { +static const struct serio_device_id taos_serio_ids[] = { { .type = SERIO_RS232, .proto = SERIO_TAOSEVM, -- cgit v1.2.3 From 8ae034c2cac93813de1fa10d7167112f71335ccd Mon Sep 17 00:00:00 2001 From: Eugeniu Rosca Date: Tue, 15 Aug 2017 22:36:23 +0200 Subject: i2c: rcar: avoid unused ret variable Fix smatch warning: drivers/i2c/busses/i2c-rcar.c:628 \ rcar_i2c_request_dma_chan() warn: unused return: ret = PTR_ERR() Signed-off-by: Eugeniu Rosca Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-rcar.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 93c1a54981df..15d764afec3b 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -625,9 +625,8 @@ static struct dma_chan *rcar_i2c_request_dma_chan(struct device *dev, chan = dma_request_chan(dev, chan_name); if (IS_ERR(chan)) { - ret = PTR_ERR(chan); - dev_dbg(dev, "request_channel failed for %s (%d)\n", - chan_name, ret); + dev_dbg(dev, "request_channel failed for %s (%ld)\n", + chan_name, PTR_ERR(chan)); return chan; } -- cgit v1.2.3 From 75fdc51832492d183f477442e406fc745546307c Mon Sep 17 00:00:00 2001 From: Eugeniu Rosca Date: Tue, 15 Aug 2017 22:36:24 +0200 Subject: i2c: sh_mobile: avoid unused ret variable Fix smatch warning: drivers/i2c/busses/i2c-sh_mobile.c:564 \ sh_mobile_i2c_request_dma_chan() warn: unused return: ret = PTR_ERR() Signed-off-by: Eugeniu Rosca Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sh_mobile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 2e097d97d258..6f2aaeb7c4fa 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -561,8 +561,8 @@ static struct dma_chan *sh_mobile_i2c_request_dma_chan(struct device *dev, chan = dma_request_slave_channel_reason(dev, chan_name); if (IS_ERR(chan)) { - ret = PTR_ERR(chan); - dev_dbg(dev, "request_channel failed for %s (%d)\n", chan_name, ret); + dev_dbg(dev, "request_channel failed for %s (%ld)\n", chan_name, + PTR_ERR(chan)); return chan; } -- cgit v1.2.3 From a5a46bd008b5a87f726859c90ab25a69e6cf9473 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 14 Aug 2017 22:17:24 +0200 Subject: i2c-cht-wc: Add locking to interrupt / smbus_xfer functions Although unlikely without locking the smbux_xfer function may miss the nack flag and further fixes in this patch-set add some more complex constructions which need protection. Signed-off-by: Hans de Goede Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-cht-wc.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c index fe5caf70c7fe..09e0df49df6b 100644 --- a/drivers/i2c/busses/i2c-cht-wc.c +++ b/drivers/i2c/busses/i2c-cht-wc.c @@ -47,6 +47,7 @@ struct cht_wc_i2c_adap { struct i2c_adapter adapter; wait_queue_head_t wait; struct irq_chip irqchip; + struct mutex adap_lock; struct mutex irqchip_lock; struct regmap *regmap; struct irq_domain *irq_domain; @@ -63,10 +64,13 @@ static irqreturn_t cht_wc_i2c_adap_thread_handler(int id, void *data) struct cht_wc_i2c_adap *adap = data; int ret, reg; + mutex_lock(&adap->adap_lock); + /* Read IRQs */ ret = regmap_read(adap->regmap, CHT_WC_EXTCHGRIRQ, ®); if (ret) { dev_err(&adap->adapter.dev, "Error reading extchgrirq reg\n"); + mutex_unlock(&adap->adap_lock); return IRQ_NONE; } @@ -80,6 +84,16 @@ static irqreturn_t cht_wc_i2c_adap_thread_handler(int id, void *data) if (ret) dev_err(&adap->adapter.dev, "Error writing extchgrirq reg\n"); + if (reg & CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK) { + adap->nack = !!(reg & CHT_WC_EXTCHGRIRQ_NACK_IRQ); + adap->done = true; + } + + mutex_unlock(&adap->adap_lock); + + if (reg & CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK) + wake_up(&adap->wait); + /* * Do NOT use handle_nested_irq here, the client irq handler will * likely want to do i2c transfers and the i2c controller uses this @@ -96,12 +110,6 @@ static irqreturn_t cht_wc_i2c_adap_thread_handler(int id, void *data) local_irq_enable(); } - if (reg & CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK) { - adap->nack = !!(reg & CHT_WC_EXTCHGRIRQ_NACK_IRQ); - adap->done = true; - wake_up(&adap->wait); - } - return IRQ_HANDLED; } @@ -119,8 +127,10 @@ static int cht_wc_i2c_adap_smbus_xfer(struct i2c_adapter *_adap, u16 addr, struct cht_wc_i2c_adap *adap = i2c_get_adapdata(_adap); int ret, reg; + mutex_lock(&adap->adap_lock); adap->nack = false; adap->done = false; + mutex_unlock(&adap->adap_lock); ret = regmap_write(adap->regmap, CHT_WC_I2C_CLIENT_ADDR, addr); if (ret) @@ -146,18 +156,18 @@ static int cht_wc_i2c_adap_smbus_xfer(struct i2c_adapter *_adap, u16 addr, ret = wait_event_timeout(adap->wait, adap->done, 3 * HZ); if (ret == 0) return -ETIMEDOUT; - if (adap->nack) - return -EIO; - if (read_write == I2C_SMBUS_READ) { + ret = 0; + mutex_lock(&adap->adap_lock); + if (adap->nack) + ret = -EIO; + else if (read_write == I2C_SMBUS_READ) { ret = regmap_read(adap->regmap, CHT_WC_I2C_RDDATA, ®); - if (ret) - return ret; - data->byte = reg; } + mutex_unlock(&adap->adap_lock); - return 0; + return ret; } static const struct i2c_algorithm cht_wc_i2c_adap_algo = { @@ -241,6 +251,7 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev) return -ENOMEM; init_waitqueue_head(&adap->wait); + mutex_init(&adap->adap_lock); mutex_init(&adap->irqchip_lock); adap->irqchip = cht_wc_i2c_irq_chip; adap->regmap = pmic->regmap; -- cgit v1.2.3 From 8de60c636e353806d43be6313987f36b03cdbf86 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 14 Aug 2017 22:17:25 +0200 Subject: i2c-cht-wc: Ack read irqs after reading the data register Testing has shown that writing 1 to clear the read-complete irq does not work until the data register has been read first. This commit fixes the driver to read the data register first, halving the amount of interrupts in most cases since we mostly read on this i2c bus. Signed-off-by: Hans de Goede Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-cht-wc.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c index 09e0df49df6b..11f7e516f1b1 100644 --- a/drivers/i2c/busses/i2c-cht-wc.c +++ b/drivers/i2c/busses/i2c-cht-wc.c @@ -55,7 +55,8 @@ struct cht_wc_i2c_adap { int client_irq; u8 irq_mask; u8 old_irq_mask; - bool nack; + int read_data; + bool io_error; bool done; }; @@ -76,6 +77,11 @@ static irqreturn_t cht_wc_i2c_adap_thread_handler(int id, void *data) reg &= ~adap->irq_mask; + /* Reads must be acked after reading the received data. */ + ret = regmap_read(adap->regmap, CHT_WC_I2C_RDDATA, &adap->read_data); + if (ret) + adap->io_error = true; + /* * Immediately ack IRQs, so that if new IRQs arrives while we're * handling the previous ones our irq will re-trigger when we're done. @@ -85,7 +91,7 @@ static irqreturn_t cht_wc_i2c_adap_thread_handler(int id, void *data) dev_err(&adap->adapter.dev, "Error writing extchgrirq reg\n"); if (reg & CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK) { - adap->nack = !!(reg & CHT_WC_EXTCHGRIRQ_NACK_IRQ); + adap->io_error |= !!(reg & CHT_WC_EXTCHGRIRQ_NACK_IRQ); adap->done = true; } @@ -125,10 +131,10 @@ static int cht_wc_i2c_adap_smbus_xfer(struct i2c_adapter *_adap, u16 addr, union i2c_smbus_data *data) { struct cht_wc_i2c_adap *adap = i2c_get_adapdata(_adap); - int ret, reg; + int ret; mutex_lock(&adap->adap_lock); - adap->nack = false; + adap->io_error = false; adap->done = false; mutex_unlock(&adap->adap_lock); @@ -159,12 +165,10 @@ static int cht_wc_i2c_adap_smbus_xfer(struct i2c_adapter *_adap, u16 addr, ret = 0; mutex_lock(&adap->adap_lock); - if (adap->nack) + if (adap->io_error) ret = -EIO; - else if (read_write == I2C_SMBUS_READ) { - ret = regmap_read(adap->regmap, CHT_WC_I2C_RDDATA, ®); - data->byte = reg; - } + else if (read_write == I2C_SMBUS_READ) + data->byte = adap->read_data; mutex_unlock(&adap->adap_lock); return ret; @@ -238,7 +242,7 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev) .addr = 0x6b, .properties = bq24190_props, }; - int ret, irq; + int ret, reg, irq; irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -264,6 +268,11 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev) /* Clear and activate i2c-adapter interrupts, disable client IRQ */ adap->old_irq_mask = adap->irq_mask = ~CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK; + + ret = regmap_read(adap->regmap, CHT_WC_I2C_RDDATA, ®); + if (ret) + return ret; + ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, ~adap->irq_mask); if (ret) return ret; -- cgit v1.2.3 From ed1094012ae82798de33bad0ba1cc5f19a005e68 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 14 Aug 2017 22:17:26 +0200 Subject: i2c-cht-wc: Workaround CHT GPIO controller IRQ issues The Cherry Trail Whiskey Cove PMIC's IRQ line is attached to one of the GPIOs of the Cherry Trail SoC. The CHT GPIO controller sometimes fails to deliver IRQs (seen when there is an IRQ storm on another pin). This commit works around this by reducing the long timeout which was a poor attempt to workaround this from 3s to 30ms and after that manually checking the status register for transfer completion by calling the threaded IRQ handler directly. This is safe todo as the entire threaded IRQ handler is protected by a mutex. Note 30ms should be more then long enough, at 100KHz any smbus single byte transaction should be finished in 4ms. Signed-off-by: Hans de Goede Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-cht-wc.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c index 11f7e516f1b1..21312eed09e4 100644 --- a/drivers/i2c/busses/i2c-cht-wc.c +++ b/drivers/i2c/busses/i2c-cht-wc.c @@ -158,10 +158,16 @@ static int cht_wc_i2c_adap_smbus_xfer(struct i2c_adapter *_adap, u16 addr, if (ret) return ret; - /* 3 second timeout, during cable plug the PMIC responds quite slow */ - ret = wait_event_timeout(adap->wait, adap->done, 3 * HZ); - if (ret == 0) - return -ETIMEDOUT; + ret = wait_event_timeout(adap->wait, adap->done, msecs_to_jiffies(30)); + if (ret == 0) { + /* + * The CHT GPIO controller serializes all IRQs, sometimes + * causing significant delays, check status manually. + */ + cht_wc_i2c_adap_thread_handler(0, adap); + if (!adap->done) + return -ETIMEDOUT; + } ret = 0; mutex_lock(&adap->adap_lock); -- cgit v1.2.3 From 234fa0ad4e9d49282391b7f9afa65d2482a2c5d0 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 2 Aug 2017 11:48:46 +0200 Subject: i2c: Documentation: i2c-topology: mention recent driver additions Specifically mention what drivers are mux-locked and parent-locked. Signed-off-by: Peter Rosin --- Documentation/i2c/i2c-topology | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/i2c/i2c-topology b/Documentation/i2c/i2c-topology index 1a014fede0b7..f74d78b53d4d 100644 --- a/Documentation/i2c/i2c-topology +++ b/Documentation/i2c/i2c-topology @@ -42,6 +42,10 @@ i2c-arb-gpio-challenge Parent-locked i2c-mux-gpio Normally parent-locked, mux-locked iff all involved gpio pins are controlled by the same i2c root adapter that they mux. +i2c-mux-gpmux Normally parent-locked, mux-locked iff + specified in device-tree. +i2c-mux-ltc4306 Mux-locked +i2c-mux-mlxcpld Parent-locked i2c-mux-pca9541 Parent-locked i2c-mux-pca954x Parent-locked i2c-mux-pinctrl Normally parent-locked, mux-locked iff @@ -50,9 +54,11 @@ i2c-mux-pinctrl Normally parent-locked, mux-locked iff i2c-mux-reg Parent-locked In drivers/iio/ +gyro/mpu3050 Mux-locked imu/inv_mpu6050/ Mux-locked In drivers/media/ +dvb-frontends/lgdt3306a Mux-locked dvb-frontends/m88ds3103 Parent-locked dvb-frontends/rtl2830 Parent-locked dvb-frontends/rtl2832 Mux-locked -- cgit v1.2.3 From fabf08a0cd63ce39287646ceea10ac34781418f4 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Tue, 1 Aug 2017 15:16:21 +0200 Subject: i2c: mux: i2c-arb-gpio-challenge: allow compiling w/o OF support It simplifies some tests. Signed-off-by: Peter Rosin --- drivers/i2c/muxes/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig index 1bba95ecc7c0..55a10946abb6 100644 --- a/drivers/i2c/muxes/Kconfig +++ b/drivers/i2c/muxes/Kconfig @@ -8,7 +8,7 @@ menu "Multiplexer I2C Chip support" config I2C_ARB_GPIO_CHALLENGE tristate "GPIO-based I2C arbitration" depends on GPIOLIB || COMPILE_TEST - depends on OF + depends on OF || COMPILE_TEST help If you say yes to this option, support will be included for an I2C multimaster arbitration scheme using GPIOs and a challenge & -- cgit v1.2.3 From 7a53df0357f5137359f01b24cdeb891e2e5cf998 Mon Sep 17 00:00:00 2001 From: Jun Gao Date: Mon, 21 Aug 2017 11:36:52 +0800 Subject: dt-bindings: i2c: modify information formats Use common name MediaTek and modify the compatible information formats of all SoCs to the same. Signed-off-by: Jun Gao Acked-by: Rob Herring Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-mtk.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-mtk.txt b/Documentation/devicetree/bindings/i2c/i2c-mtk.txt index bd5a7befd951..9c86424c39a0 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mtk.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-mtk.txt @@ -1,14 +1,14 @@ -* Mediatek's I2C controller +* MediaTek's I2C controller -The Mediatek's I2C controller is used to interface with I2C devices. +The MediaTek's I2C controller is used to interface with I2C devices. Required properties: - compatible: value should be either of the following. - "mediatek,mt2701-i2c", "mediatek,mt6577-i2c": for Mediatek mt2701 - "mediatek,mt6577-i2c": for i2c compatible with mt6577. - "mediatek,mt6589-i2c": for i2c compatible with mt6589. - "mediatek,mt7623-i2c", "mediatek,mt6577-i2c": for i2c compatible with mt7623. - "mediatek,mt8173-i2c": for i2c compatible with mt8173. + "mediatek,mt2701-i2c", "mediatek,mt6577-i2c": for MediaTek MT2701 + "mediatek,mt6577-i2c": for MediaTek MT6577 + "mediatek,mt6589-i2c": for MediaTek MT6589 + "mediatek,mt7623-i2c", "mediatek,mt6577-i2c": for MediaTek MT7623 + "mediatek,mt8173-i2c": for MediaTek MT8173 - reg: physical base address of the controller and dma base, length of memory mapped region. - interrupts: interrupt number to the cpu. -- cgit v1.2.3 From c50b2e9379df66eadc1b8b780dd4c287aba8da8f Mon Sep 17 00:00:00 2001 From: Jun Gao Date: Mon, 21 Aug 2017 11:36:53 +0800 Subject: dt-bindings: i2c: Add MediaTek MT7622 i2c binding Add MT7622 i2c binding to binding file. Compare to MT8173 i2c controller, MT7622 limits message numbers to 255, and does not support 4GB DMA mode. Signed-off-by: Jun Gao Acked-by: Rob Herring Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-mtk.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/i2c/i2c-mtk.txt b/Documentation/devicetree/bindings/i2c/i2c-mtk.txt index 9c86424c39a0..ff7bf37deb43 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mtk.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-mtk.txt @@ -7,6 +7,7 @@ Required properties: "mediatek,mt2701-i2c", "mediatek,mt6577-i2c": for MediaTek MT2701 "mediatek,mt6577-i2c": for MediaTek MT6577 "mediatek,mt6589-i2c": for MediaTek MT6589 + "mediatek,mt7622-i2c": for MediaTek MT7622 "mediatek,mt7623-i2c", "mediatek,mt6577-i2c": for MediaTek MT7623 "mediatek,mt8173-i2c": for MediaTek MT8173 - reg: physical base address of the controller and dma base, length of memory -- cgit v1.2.3 From 1304fe0916eeb67c78309e54eb819f8b4932ed33 Mon Sep 17 00:00:00 2001 From: Jun Gao Date: Mon, 21 Aug 2017 11:36:54 +0800 Subject: i2c: mediatek: Add i2c compatible for MediaTek MT7622 Add i2c compatible for MT7622. Compare to MT8173 i2c controller, MT7622 limits message numbers to 255, and does not support 4GB DMA mode. Signed-off-by: Jun Gao Reviewed-by: Yingjoe Chen Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mt65xx.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index 9bedf0bf2c4d..09d288ce0ddb 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -172,6 +172,10 @@ static const struct i2c_adapter_quirks mt6577_i2c_quirks = { .max_comb_2nd_msg_len = 31, }; +static const struct i2c_adapter_quirks mt7622_i2c_quirks = { + .max_num_msgs = 255, +}; + static const struct mtk_i2c_compatible mt6577_compat = { .quirks = &mt6577_i2c_quirks, .pmic_i2c = 0, @@ -190,6 +194,15 @@ static const struct mtk_i2c_compatible mt6589_compat = { .support_33bits = 0, }; +static const struct mtk_i2c_compatible mt7622_compat = { + .quirks = &mt7622_i2c_quirks, + .pmic_i2c = 0, + .dcm = 1, + .auto_restart = 1, + .aux_len_reg = 1, + .support_33bits = 0, +}; + static const struct mtk_i2c_compatible mt8173_compat = { .pmic_i2c = 0, .dcm = 1, @@ -201,6 +214,7 @@ static const struct mtk_i2c_compatible mt8173_compat = { static const struct of_device_id mtk_i2c_of_match[] = { { .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat }, { .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat }, + { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat }, { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat }, {} }; -- cgit v1.2.3 From cc209ac81cce0109e03af23f68ea06b549a4a2ed Mon Sep 17 00:00:00 2001 From: Franklin S Cooper Jr Date: Wed, 16 Aug 2017 17:17:13 -0500 Subject: i2c: davinci: Preserve return value of devm_clk_get The i2c driver can run into driver dependency issues if its loaded before a clock driver it depends on. Therefore, EPROBE_DEFER may be returned by devm_clk_get and should be returned in probe to allow the kernel to reprobe the driver at a later time. This patch allows the error value returned by devm_clk_get to be passed through and not overwritten. Signed-off-by: Franklin S Cooper Jr Reviewed-by: Grygorii Strashko Acked-by: Sekhar Nori Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-davinci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 33ca9a336182..b8c43535f16c 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -801,7 +801,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) dev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(dev->clk)) - return -ENODEV; + return PTR_ERR(dev->clk); clk_prepare_enable(dev->clk); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- cgit v1.2.3 From a1cc5a57e49e871ce5e610597af1bd6bea06cb5c Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 13 Aug 2017 16:21:17 +0200 Subject: blackfin: merge the two TWI header files There seems to be no need for separate ones since all users include both files anyhow. Merge them because include/linux/i2c is to be deprecated. Signed-off-by: Wolfram Sang --- arch/blackfin/include/asm/bfin_twi.h | 134 +++++++++++++++++++++++++++++++- arch/blackfin/kernel/debug-mmrs.c | 1 - drivers/i2c/busses/i2c-bfin-twi.c | 1 - include/linux/i2c/bfin_twi.h | 145 ----------------------------------- 4 files changed, 133 insertions(+), 148 deletions(-) delete mode 100644 include/linux/i2c/bfin_twi.h diff --git a/arch/blackfin/include/asm/bfin_twi.h b/arch/blackfin/include/asm/bfin_twi.h index aaa0834d34aa..211e9c78f6fb 100644 --- a/arch/blackfin/include/asm/bfin_twi.h +++ b/arch/blackfin/include/asm/bfin_twi.h @@ -1,7 +1,7 @@ /* * bfin_twi.h - interface to Blackfin TWIs * - * Copyright 2005-2010 Analog Devices Inc. + * Copyright 2005-2014 Analog Devices Inc. * * Licensed under the GPL-2 or later. */ @@ -10,6 +10,138 @@ #define __ASM_BFIN_TWI_H__ #include +#include +#include + +/* + * ADI twi registers layout + */ +struct bfin_twi_regs { + u16 clkdiv; + u16 dummy1; + u16 control; + u16 dummy2; + u16 slave_ctl; + u16 dummy3; + u16 slave_stat; + u16 dummy4; + u16 slave_addr; + u16 dummy5; + u16 master_ctl; + u16 dummy6; + u16 master_stat; + u16 dummy7; + u16 master_addr; + u16 dummy8; + u16 int_stat; + u16 dummy9; + u16 int_mask; + u16 dummy10; + u16 fifo_ctl; + u16 dummy11; + u16 fifo_stat; + u16 dummy12; + u32 __pad[20]; + u16 xmt_data8; + u16 dummy13; + u16 xmt_data16; + u16 dummy14; + u16 rcv_data8; + u16 dummy15; + u16 rcv_data16; + u16 dummy16; +}; + +struct bfin_twi_iface { + int irq; + spinlock_t lock; + char read_write; + u8 command; + u8 *transPtr; + int readNum; + int writeNum; + int cur_mode; + int manual_stop; + int result; + struct i2c_adapter adap; + struct completion complete; + struct i2c_msg *pmsg; + int msg_num; + int cur_msg; + u16 saved_clkdiv; + u16 saved_control; + struct bfin_twi_regs __iomem *regs_base; +}; + +/* ******************** TWO-WIRE INTERFACE (TWI) MASKS ********************/ +/* TWI_CLKDIV Macros (Use: *pTWI_CLKDIV = CLKLOW(x)|CLKHI(y); ) */ +#define CLKLOW(x) ((x) & 0xFF) /* Periods Clock Is Held Low */ +#define CLKHI(y) (((y)&0xFF)<<0x8) /* Periods Before New Clock Low */ + +/* TWI_PRESCALE Masks */ +#define PRESCALE 0x007F /* SCLKs Per Internal Time Reference (10MHz) */ +#define TWI_ENA 0x0080 /* TWI Enable */ +#define SCCB 0x0200 /* SCCB Compatibility Enable */ + +/* TWI_SLAVE_CTL Masks */ +#define SEN 0x0001 /* Slave Enable */ +#define SADD_LEN 0x0002 /* Slave Address Length */ +#define STDVAL 0x0004 /* Slave Transmit Data Valid */ +#define NAK 0x0008 /* NAK Generated At Conclusion Of Transfer */ +#define GEN 0x0010 /* General Call Address Matching Enabled */ + +/* TWI_SLAVE_STAT Masks */ +#define SDIR 0x0001 /* Slave Transfer Direction (RX/TX*) */ +#define GCALL 0x0002 /* General Call Indicator */ + +/* TWI_MASTER_CTL Masks */ +#define MEN 0x0001 /* Master Mode Enable */ +#define MADD_LEN 0x0002 /* Master Address Length */ +#define MDIR 0x0004 /* Master Transmit Direction (RX/TX*) */ +#define FAST 0x0008 /* Use Fast Mode Timing Specs */ +#define STOP 0x0010 /* Issue Stop Condition */ +#define RSTART 0x0020 /* Repeat Start or Stop* At End Of Transfer */ +#define DCNT 0x3FC0 /* Data Bytes To Transfer */ +#define SDAOVR 0x4000 /* Serial Data Override */ +#define SCLOVR 0x8000 /* Serial Clock Override */ + +/* TWI_MASTER_STAT Masks */ +#define MPROG 0x0001 /* Master Transfer In Progress */ +#define LOSTARB 0x0002 /* Lost Arbitration Indicator (Xfer Aborted) */ +#define ANAK 0x0004 /* Address Not Acknowledged */ +#define DNAK 0x0008 /* Data Not Acknowledged */ +#define BUFRDERR 0x0010 /* Buffer Read Error */ +#define BUFWRERR 0x0020 /* Buffer Write Error */ +#define SDASEN 0x0040 /* Serial Data Sense */ +#define SCLSEN 0x0080 /* Serial Clock Sense */ +#define BUSBUSY 0x0100 /* Bus Busy Indicator */ + +/* TWI_INT_SRC and TWI_INT_ENABLE Masks */ +#define SINIT 0x0001 /* Slave Transfer Initiated */ +#define SCOMP 0x0002 /* Slave Transfer Complete */ +#define SERR 0x0004 /* Slave Transfer Error */ +#define SOVF 0x0008 /* Slave Overflow */ +#define MCOMP 0x0010 /* Master Transfer Complete */ +#define MERR 0x0020 /* Master Transfer Error */ +#define XMTSERV 0x0040 /* Transmit FIFO Service */ +#define RCVSERV 0x0080 /* Receive FIFO Service */ + +/* TWI_FIFO_CTRL Masks */ +#define XMTFLUSH 0x0001 /* Transmit Buffer Flush */ +#define RCVFLUSH 0x0002 /* Receive Buffer Flush */ +#define XMTINTLEN 0x0004 /* Transmit Buffer Interrupt Length */ +#define RCVINTLEN 0x0008 /* Receive Buffer Interrupt Length */ + +/* TWI_FIFO_STAT Masks */ +#define XMTSTAT 0x0003 /* Transmit FIFO Status */ +#define XMT_EMPTY 0x0000 /* Transmit FIFO Empty */ +#define XMT_HALF 0x0001 /* Transmit FIFO Has 1 Byte To Write */ +#define XMT_FULL 0x0003 /* Transmit FIFO Full (2 Bytes To Write) */ + +#define RCVSTAT 0x000C /* Receive FIFO Status */ +#define RCV_EMPTY 0x0000 /* Receive FIFO Empty */ +#define RCV_HALF 0x0004 /* Receive FIFO Has 1 Byte To Read */ +#define RCV_FULL 0x000C /* Receive FIFO Full (2 Bytes To Read) */ #define DEFINE_TWI_REG(reg_name, reg) \ static inline u16 read_##reg_name(struct bfin_twi_iface *iface) \ diff --git a/arch/blackfin/kernel/debug-mmrs.c b/arch/blackfin/kernel/debug-mmrs.c index e272bca93c64..f31ace221392 100644 --- a/arch/blackfin/kernel/debug-mmrs.c +++ b/arch/blackfin/kernel/debug-mmrs.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index 9fe942b8c610..ff3343186a82 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include diff --git a/include/linux/i2c/bfin_twi.h b/include/linux/i2c/bfin_twi.h deleted file mode 100644 index 135a4e0876ae..000000000000 --- a/include/linux/i2c/bfin_twi.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * i2c-bfin-twi.h - interface to ADI TWI controller - * - * Copyright 2005-2014 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#ifndef __I2C_BFIN_TWI_H__ -#define __I2C_BFIN_TWI_H__ - -#include -#include - -/* - * ADI twi registers layout - */ -struct bfin_twi_regs { - u16 clkdiv; - u16 dummy1; - u16 control; - u16 dummy2; - u16 slave_ctl; - u16 dummy3; - u16 slave_stat; - u16 dummy4; - u16 slave_addr; - u16 dummy5; - u16 master_ctl; - u16 dummy6; - u16 master_stat; - u16 dummy7; - u16 master_addr; - u16 dummy8; - u16 int_stat; - u16 dummy9; - u16 int_mask; - u16 dummy10; - u16 fifo_ctl; - u16 dummy11; - u16 fifo_stat; - u16 dummy12; - u32 __pad[20]; - u16 xmt_data8; - u16 dummy13; - u16 xmt_data16; - u16 dummy14; - u16 rcv_data8; - u16 dummy15; - u16 rcv_data16; - u16 dummy16; -}; - -struct bfin_twi_iface { - int irq; - spinlock_t lock; - char read_write; - u8 command; - u8 *transPtr; - int readNum; - int writeNum; - int cur_mode; - int manual_stop; - int result; - struct i2c_adapter adap; - struct completion complete; - struct i2c_msg *pmsg; - int msg_num; - int cur_msg; - u16 saved_clkdiv; - u16 saved_control; - struct bfin_twi_regs __iomem *regs_base; -}; - -/* ******************** TWO-WIRE INTERFACE (TWI) MASKS ********************/ -/* TWI_CLKDIV Macros (Use: *pTWI_CLKDIV = CLKLOW(x)|CLKHI(y); ) */ -#define CLKLOW(x) ((x) & 0xFF) /* Periods Clock Is Held Low */ -#define CLKHI(y) (((y)&0xFF)<<0x8) /* Periods Before New Clock Low */ - -/* TWI_PRESCALE Masks */ -#define PRESCALE 0x007F /* SCLKs Per Internal Time Reference (10MHz) */ -#define TWI_ENA 0x0080 /* TWI Enable */ -#define SCCB 0x0200 /* SCCB Compatibility Enable */ - -/* TWI_SLAVE_CTL Masks */ -#define SEN 0x0001 /* Slave Enable */ -#define SADD_LEN 0x0002 /* Slave Address Length */ -#define STDVAL 0x0004 /* Slave Transmit Data Valid */ -#define NAK 0x0008 /* NAK Generated At Conclusion Of Transfer */ -#define GEN 0x0010 /* General Call Address Matching Enabled */ - -/* TWI_SLAVE_STAT Masks */ -#define SDIR 0x0001 /* Slave Transfer Direction (RX/TX*) */ -#define GCALL 0x0002 /* General Call Indicator */ - -/* TWI_MASTER_CTL Masks */ -#define MEN 0x0001 /* Master Mode Enable */ -#define MADD_LEN 0x0002 /* Master Address Length */ -#define MDIR 0x0004 /* Master Transmit Direction (RX/TX*) */ -#define FAST 0x0008 /* Use Fast Mode Timing Specs */ -#define STOP 0x0010 /* Issue Stop Condition */ -#define RSTART 0x0020 /* Repeat Start or Stop* At End Of Transfer */ -#define DCNT 0x3FC0 /* Data Bytes To Transfer */ -#define SDAOVR 0x4000 /* Serial Data Override */ -#define SCLOVR 0x8000 /* Serial Clock Override */ - -/* TWI_MASTER_STAT Masks */ -#define MPROG 0x0001 /* Master Transfer In Progress */ -#define LOSTARB 0x0002 /* Lost Arbitration Indicator (Xfer Aborted) */ -#define ANAK 0x0004 /* Address Not Acknowledged */ -#define DNAK 0x0008 /* Data Not Acknowledged */ -#define BUFRDERR 0x0010 /* Buffer Read Error */ -#define BUFWRERR 0x0020 /* Buffer Write Error */ -#define SDASEN 0x0040 /* Serial Data Sense */ -#define SCLSEN 0x0080 /* Serial Clock Sense */ -#define BUSBUSY 0x0100 /* Bus Busy Indicator */ - -/* TWI_INT_SRC and TWI_INT_ENABLE Masks */ -#define SINIT 0x0001 /* Slave Transfer Initiated */ -#define SCOMP 0x0002 /* Slave Transfer Complete */ -#define SERR 0x0004 /* Slave Transfer Error */ -#define SOVF 0x0008 /* Slave Overflow */ -#define MCOMP 0x0010 /* Master Transfer Complete */ -#define MERR 0x0020 /* Master Transfer Error */ -#define XMTSERV 0x0040 /* Transmit FIFO Service */ -#define RCVSERV 0x0080 /* Receive FIFO Service */ - -/* TWI_FIFO_CTRL Masks */ -#define XMTFLUSH 0x0001 /* Transmit Buffer Flush */ -#define RCVFLUSH 0x0002 /* Receive Buffer Flush */ -#define XMTINTLEN 0x0004 /* Transmit Buffer Interrupt Length */ -#define RCVINTLEN 0x0008 /* Receive Buffer Interrupt Length */ - -/* TWI_FIFO_STAT Masks */ -#define XMTSTAT 0x0003 /* Transmit FIFO Status */ -#define XMT_EMPTY 0x0000 /* Transmit FIFO Empty */ -#define XMT_HALF 0x0001 /* Transmit FIFO Has 1 Byte To Write */ -#define XMT_FULL 0x0003 /* Transmit FIFO Full (2 Bytes To Write) */ - -#define RCVSTAT 0x000C /* Receive FIFO Status */ -#define RCV_EMPTY 0x0000 /* Receive FIFO Empty */ -#define RCV_HALF 0x0004 /* Receive FIFO Has 1 Byte To Read */ -#define RCV_FULL 0x000C /* Receive FIFO Full (2 Bytes To Read) */ - -#endif -- cgit v1.2.3 From b505ae158309ab39c423b5a484031526ca4b7372 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 13 Aug 2017 17:34:31 +0200 Subject: MAINTAINERS: drop entry for Blackfin I2C and Sonic's email Sonic's email address bounced, so remove it from MAINTAINERS. Since there was no I2C/TWI maintenance activity for 3 years now, drop that whole entry. Signed-off-by: Wolfram Sang --- MAINTAINERS | 9 --------- 1 file changed, 9 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 44cb004c765d..19256dcb371d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2546,13 +2546,6 @@ W: http://blackfin.uclinux.org S: Supported F: drivers/net/ethernet/adi/ -BLACKFIN I2C TWI DRIVER -M: Sonic Zhang -L: adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers) -W: http://blackfin.uclinux.org/ -S: Supported -F: drivers/i2c/busses/i2c-bfin-twi.c - BLACKFIN MEDIA DRIVER M: Scott Jiang L: adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers) @@ -2569,14 +2562,12 @@ S: Supported F: drivers/rtc/rtc-bfin.c BLACKFIN SDH DRIVER -M: Sonic Zhang L: adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers) W: http://blackfin.uclinux.org S: Supported F: drivers/mmc/host/bfin_sdh.c BLACKFIN SERIAL DRIVER -M: Sonic Zhang L: adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers) W: http://blackfin.uclinux.org S: Supported -- cgit v1.2.3 From bfd4473b850c8cfaa1cdf56b8ef52fae4e8a6ee5 Mon Sep 17 00:00:00 2001 From: Qiuxu Zhuo Date: Tue, 15 Aug 2017 00:04:50 +0800 Subject: i2c: i801: Restore the presence state of P2SB PCI device after reading BAR Sun, Yunying reported the following failure on Denverton micro-server: EDAC DEBUG: pnd2_init: EDAC DEBUG: pnd2_probe: EDAC DEBUG: dnv_rd_reg: Read b_cr_tolud_pci=00000000_80000000 EDAC DEBUG: dnv_rd_reg: Read b_cr_touud_lo_pci=00000000_80000000 EDAC DEBUG: dnv_rd_reg: Read b_cr_touud_hi_pci=00000000_00000004 EDAC DEBUG: dnv_rd_reg: Read b_cr_asym_mem_region0_mchbar=00000000_00000000 EDAC DEBUG: dnv_rd_reg: Read b_cr_asym_mem_region1_mchbar=00000000_00000000 EDAC DEBUG: dnv_rd_reg: Read b_cr_mot_out_base_mchbar=00000000_00000000 EDAC DEBUG: dnv_rd_reg: Read b_cr_mot_out_mask_mchbar=00000000_00000000 EDAC pnd2: Failed to register device with error -19. On Denverton micro-server, the presence of the P2SB bridge PCI device is enabled or disabled by the item 'RelaxSecConf' in BIOS setup menu. When 'RelaxSecConf' is enabled, the P2SB PCI device is present and the pnd2_edac EDAC driver also uses it to get BAR. Hiding the P2SB PCI device caused the pnd2_edac EDAC driver failed to get BAR then reported the above failure. Therefor, store the presence state of P2SB PCI device before unhiding it for reading BAR and restore the presence state after reading BAR. Signed-off-by: Qiuxu Zhuo Reported-by: Yunying Sun Tested-by: Yunying Sun Reviewed-by: Mika Westerberg Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-i801.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index c9536e17d6ff..e114e4e00d29 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1332,6 +1332,7 @@ static void i801_add_tco(struct i801_priv *priv) u32 tco_base, tco_ctl; u32 base_addr, ctrl_val; u64 base64_addr; + u8 hidden; if (!(priv->features & FEATURE_TCO)) return; @@ -1376,8 +1377,10 @@ static void i801_add_tco(struct i801_priv *priv) devfn = PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 1); - /* Unhide the P2SB device */ - pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, 0x0); + /* Unhide the P2SB device, if it is hidden */ + pci_bus_read_config_byte(pci_dev->bus, devfn, 0xe1, &hidden); + if (hidden) + pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, 0x0); pci_bus_read_config_dword(pci_dev->bus, devfn, SBREG_BAR, &base_addr); base64_addr = base_addr & 0xfffffff0; @@ -1385,8 +1388,9 @@ static void i801_add_tco(struct i801_priv *priv) pci_bus_read_config_dword(pci_dev->bus, devfn, SBREG_BAR + 0x4, &base_addr); base64_addr |= (u64)base_addr << 32; - /* Hide the P2SB device */ - pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, 0x1); + /* Hide the P2SB device, if it was hidden before */ + if (hidden) + pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, hidden); spin_unlock(&p2sb_spinlock); res = &tco_res[ICH_RES_MEM_OFF]; -- cgit v1.2.3 From 2f13f8c50ae21ce70a437149a0e221755e554912 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 15 Jun 2017 20:54:03 +0200 Subject: dt-bindings: i2c: eeprom: Document vendor to be used and deprecated ones The at24 driver allows to register I2C EEPROM chips using different vendor and devices, but the I2C subsystem does not take the vendor into account when matching using the I2C table since it only has device entries. But when matching using an OF table, both the vendor and device has to be taken into account so the driver defines only a set of compatible strings using the "atmel" vendor as a generic fallback for compatible I2C devices. Document in the Device Tree binding document that this manufacturer should be used as the generic fallback. Also document the deprecated vendors. Suggested-by: Wolfram Sang Suggested-by: Rob Herring Signed-off-by: Javier Martinez Canillas Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/eeprom/eeprom.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/eeprom/eeprom.txt b/Documentation/devicetree/bindings/eeprom/eeprom.txt index 5696eb508e95..afc04589eadf 100644 --- a/Documentation/devicetree/bindings/eeprom/eeprom.txt +++ b/Documentation/devicetree/bindings/eeprom/eeprom.txt @@ -16,8 +16,12 @@ Required properties: "renesas,r1ex24002" + The following manufacturers values have been deprecated: + "at", "at24" + If there is no specific driver for , a generic - driver based on is selected. Possible types are: + device with and manufacturer "atmel" should be used. + Possible types are: "24c00", "24c01", "24c02", "24c04", "24c08", "24c16", "24c32", "24c64", "24c128", "24c256", "24c512", "24c1024", "spd" -- cgit v1.2.3 From 95fd3ad9cd5f8a4bb01215b846a3c8e6adefe21c Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Tue, 15 Aug 2017 16:51:02 +0930 Subject: i2c: aspeed: Retain delay/setup/hold values when configuring bus frequency In addition to the base, low and high clock configuration, the AC timing register #1 on the AST2400 houses fields controlling: 1. tBUF: Minimum delay between Stop and Start conditions 2. tHDSTA: Hold time for the Start condition 3. tACST: Setup time for Start and Stop conditions, and hold time for the Repeated Start condition These values are defined in hardware on the AST2500 and therefore don't need to be set. aspeed_i2c_init_clk() was performing a direct write of the generated clock values rather than a read/mask/modify/update sequence to retain tBUF, tHDSTA and tACST, and therefore cleared the tBUF, tHDSTA and tACST fields on the AST2400. This resulted in a delay/setup/hold time of 1 base clock, which in some configurations is not enough for some devices (e.g. the MAX31785 fan controller, with an APB of 48MHz and a desired bus speed of 100kHz). Signed-off-by: Andrew Jeffery Reviewed-by: Brendan Higgins Tested-by: Brendan Higgins Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-aspeed.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index 60afab866494..645e0076f723 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -53,6 +53,9 @@ #define ASPEED_I2CD_MASTER_EN BIT(0) /* 0x04 : I2CD Clock and AC Timing Control Register #1 */ +#define ASPEED_I2CD_TIME_TBUF_MASK GENMASK(31, 28) +#define ASPEED_I2CD_TIME_THDSTA_MASK GENMASK(27, 24) +#define ASPEED_I2CD_TIME_TACST_MASK GENMASK(23, 20) #define ASPEED_I2CD_TIME_SCL_HIGH_SHIFT 16 #define ASPEED_I2CD_TIME_SCL_HIGH_MASK GENMASK(19, 16) #define ASPEED_I2CD_TIME_SCL_LOW_SHIFT 12 @@ -743,7 +746,11 @@ static int aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus) u32 divisor, clk_reg_val; divisor = DIV_ROUND_UP(bus->parent_clk_frequency, bus->bus_frequency); - clk_reg_val = bus->get_clk_reg_val(divisor); + clk_reg_val = readl(bus->base + ASPEED_I2C_AC_TIMING_REG1); + clk_reg_val &= (ASPEED_I2CD_TIME_TBUF_MASK | + ASPEED_I2CD_TIME_THDSTA_MASK | + ASPEED_I2CD_TIME_TACST_MASK); + clk_reg_val |= bus->get_clk_reg_val(divisor); writel(clk_reg_val, bus->base + ASPEED_I2C_AC_TIMING_REG1); writel(ASPEED_NO_TIMEOUT_CTRL, bus->base + ASPEED_I2C_AC_TIMING_REG2); -- cgit v1.2.3 From d596f2b8b4cb0451087992796974aa9f076a7fc7 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 28 Aug 2017 18:40:29 +0200 Subject: MAINTAINERS: Add entry for drivers/i2c/busses/i2c-cht-wc.c Add an entry for drivers/i2c/busses/i2c-cht-wc.c and add myself as maintainer of this driver. Signed-off-by: Hans de Goede Signed-off-by: Wolfram Sang --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 19256dcb371d..ea4f6f7a8f2a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6362,6 +6362,12 @@ F: drivers/i2c/busses/i2c-sis96x.c F: drivers/i2c/busses/i2c-via.c F: drivers/i2c/busses/i2c-viapro.c +I2C/SMBUS INTEL CHT WHISKEY COVE PMIC DRIVER +M: Hans de Goede +L: linux-i2c@vger.kernel.org +S: Maintained +F: drivers/i2c/busses/i2c-cht-wc.c + I2C/SMBUS ISMT DRIVER M: Seth Heasley M: Neil Horman -- cgit v1.2.3 From 5ca21c13c9f4d180e673bcbc36fd0d9128b7f63e Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 16 Aug 2017 10:16:59 +0100 Subject: i2c-cht-wc: make cht_wc_i2c_adap_driver static The structure cht_wc_i2c_adap_driver is local to the source and does not need to be in global scope, so make it static. Cleans up sparse warning: symbol 'cht_wc_i2c_adap_driver' was not declared. Should it be static? Signed-off-by: Colin Ian King Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-cht-wc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c index 21312eed09e4..190bbbc7bfee 100644 --- a/drivers/i2c/busses/i2c-cht-wc.c +++ b/drivers/i2c/busses/i2c-cht-wc.c @@ -348,7 +348,7 @@ static struct platform_device_id cht_wc_i2c_adap_id_table[] = { }; MODULE_DEVICE_TABLE(platform, cht_wc_i2c_adap_id_table); -struct platform_driver cht_wc_i2c_adap_driver = { +static struct platform_driver cht_wc_i2c_adap_driver = { .probe = cht_wc_i2c_adap_i2c_probe, .remove = cht_wc_i2c_adap_i2c_remove, .driver = { -- cgit v1.2.3 From 4058f6dc3b8ec631865f63e59fb79e86145243a4 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Tue, 29 Aug 2017 11:35:03 +0800 Subject: dt-bindings: i2c: Add Spreadtrum I2C controller documentation This patch adds the binding documentation for Spreadtrum I2C controller device. Signed-off-by: Baolin Wang Acked-by: Rob Herring Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-sprd.txt | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 Documentation/devicetree/bindings/i2c/i2c-sprd.txt diff --git a/Documentation/devicetree/bindings/i2c/i2c-sprd.txt b/Documentation/devicetree/bindings/i2c/i2c-sprd.txt new file mode 100644 index 000000000000..60b7cda15dd2 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/i2c-sprd.txt @@ -0,0 +1,31 @@ +I2C for Spreadtrum platforms + +Required properties: +- compatible: Should be "sprd,sc9860-i2c". +- reg: Specify the physical base address of the controller and length + of memory mapped region. +- interrupts: Should contain I2C interrupt. +- clock-names: Should contain following entries: + "i2c" for I2C clock, + "source" for I2C source (parent) clock, + "enable" for I2C module enable clock. +- clocks: Should contain a clock specifier for each entry in clock-names. +- clock-frequency: Constains desired I2C bus clock frequency in Hz. +- #address-cells: Should be 1 to describe address cells for I2C device address. +- #size-cells: Should be 0 means no size cell for I2C device address. + +Optional properties: +- Child nodes conforming to I2C bus binding + +Examples: +i2c0: i2c@70500000 { + compatible = "sprd,sc9860-i2c"; + reg = <0 0x70500000 0 0x1000>; + interrupts = ; + clock-names = "i2c", "source", "enable"; + clocks = <&clk_i2c3>, <&ext_26m>, <&clk_ap_apb_gates 11>; + clock-frequency = <400000>; + #address-cells = <1>; + #size-cells = <0>; +}; + -- cgit v1.2.3 From 8b9ec0719834fe66146d138d62ed66cef025c864 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Tue, 29 Aug 2017 11:35:04 +0800 Subject: i2c: Add Spreadtrum I2C controller driver This patch adds the I2C controller driver for Spreadtrum SC9860 platform. Signed-off-by: Baolin Wang Reviewed-by: Andy Shevchenko Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Kconfig | 7 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-sprd.c | 646 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 654 insertions(+) create mode 100644 drivers/i2c/busses/i2c-sprd.c diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index f20b1f84013a..1bd3e5fc337b 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -908,6 +908,13 @@ config I2C_SIRF This driver can also be built as a module. If so, the module will be called i2c-sirf. +config I2C_SPRD + bool "Spreadtrum I2C interface" + depends on ARCH_SPRD + help + If you say yes to this option, support will be included for the + Spreadtrum I2C interface. + config I2C_ST tristate "STMicroelectronics SSC I2C support" depends on ARCH_STI diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 4e654b5dbe6f..562daf738048 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -90,6 +90,7 @@ obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o obj-$(CONFIG_I2C_SIRF) += i2c-sirf.o +obj-$(CONFIG_I2C_SPRD) += i2c-sprd.o obj-$(CONFIG_I2C_ST) += i2c-st.o obj-$(CONFIG_I2C_STM32F4) += i2c-stm32f4.o obj-$(CONFIG_I2C_STU300) += i2c-stu300.o diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c new file mode 100644 index 000000000000..22e08ae1704f --- /dev/null +++ b/drivers/i2c/busses/i2c-sprd.c @@ -0,0 +1,646 @@ +/* + * Copyright (C) 2017 Spreadtrum Communications Inc. + * + * SPDX-License-Identifier: (GPL-2.0+ OR MIT) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_CTL 0x00 +#define I2C_ADDR_CFG 0x04 +#define I2C_COUNT 0x08 +#define I2C_RX 0x0c +#define I2C_TX 0x10 +#define I2C_STATUS 0x14 +#define I2C_HSMODE_CFG 0x18 +#define I2C_VERSION 0x1c +#define ADDR_DVD0 0x20 +#define ADDR_DVD1 0x24 +#define ADDR_STA0_DVD 0x28 +#define ADDR_RST 0x2c + +/* I2C_CTL */ +#define STP_EN BIT(20) +#define FIFO_AF_LVL_MASK GENMASK(19, 16) +#define FIFO_AF_LVL 16 +#define FIFO_AE_LVL_MASK GENMASK(15, 12) +#define FIFO_AE_LVL 12 +#define I2C_DMA_EN BIT(11) +#define FULL_INTEN BIT(10) +#define EMPTY_INTEN BIT(9) +#define I2C_DVD_OPT BIT(8) +#define I2C_OUT_OPT BIT(7) +#define I2C_TRIM_OPT BIT(6) +#define I2C_HS_MODE BIT(4) +#define I2C_MODE BIT(3) +#define I2C_EN BIT(2) +#define I2C_INT_EN BIT(1) +#define I2C_START BIT(0) + +/* I2C_STATUS */ +#define SDA_IN BIT(21) +#define SCL_IN BIT(20) +#define FIFO_FULL BIT(4) +#define FIFO_EMPTY BIT(3) +#define I2C_INT BIT(2) +#define I2C_RX_ACK BIT(1) +#define I2C_BUSY BIT(0) + +/* ADDR_RST */ +#define I2C_RST BIT(0) + +#define I2C_FIFO_DEEP 12 +#define I2C_FIFO_FULL_THLD 15 +#define I2C_FIFO_EMPTY_THLD 4 +#define I2C_DATA_STEP 8 +#define I2C_ADDR_DVD0_CALC(high, low) \ + ((((high) & GENMASK(15, 0)) << 16) | ((low) & GENMASK(15, 0))) +#define I2C_ADDR_DVD1_CALC(high, low) \ + (((high) & GENMASK(31, 16)) | (((low) & GENMASK(31, 16)) >> 16)) + +/* timeout (ms) for pm runtime autosuspend */ +#define SPRD_I2C_PM_TIMEOUT 1000 + +/* SPRD i2c data structure */ +struct sprd_i2c { + struct i2c_adapter adap; + struct device *dev; + void __iomem *base; + struct i2c_msg *msg; + struct clk *clk; + u32 src_clk; + u32 bus_freq; + struct completion complete; + u8 *buf; + u32 count; + int irq; + int err; +}; + +static void sprd_i2c_set_count(struct sprd_i2c *i2c_dev, u32 count) +{ + writel(count, i2c_dev->base + I2C_COUNT); +} + +static void sprd_i2c_send_stop(struct sprd_i2c *i2c_dev, int stop) +{ + u32 tmp = readl(i2c_dev->base + I2C_CTL); + + if (stop) + writel(tmp & ~STP_EN, i2c_dev->base + I2C_CTL); + else + writel(tmp | STP_EN, i2c_dev->base + I2C_CTL); +} + +static void sprd_i2c_clear_start(struct sprd_i2c *i2c_dev) +{ + u32 tmp = readl(i2c_dev->base + I2C_CTL); + + writel(tmp & ~I2C_START, i2c_dev->base + I2C_CTL); +} + +static void sprd_i2c_clear_ack(struct sprd_i2c *i2c_dev) +{ + u32 tmp = readl(i2c_dev->base + I2C_STATUS); + + writel(tmp & ~I2C_RX_ACK, i2c_dev->base + I2C_STATUS); +} + +static void sprd_i2c_clear_irq(struct sprd_i2c *i2c_dev) +{ + u32 tmp = readl(i2c_dev->base + I2C_STATUS); + + writel(tmp & ~I2C_INT, i2c_dev->base + I2C_STATUS); +} + +static void sprd_i2c_reset_fifo(struct sprd_i2c *i2c_dev) +{ + writel(I2C_RST, i2c_dev->base + ADDR_RST); +} + +static void sprd_i2c_set_devaddr(struct sprd_i2c *i2c_dev, struct i2c_msg *m) +{ + writel(m->addr << 1, i2c_dev->base + I2C_ADDR_CFG); +} + +static void sprd_i2c_write_bytes(struct sprd_i2c *i2c_dev, u8 *buf, u32 len) +{ + u32 i; + + for (i = 0; i < len; i++) + writeb(buf[i], i2c_dev->base + I2C_TX); +} + +static void sprd_i2c_read_bytes(struct sprd_i2c *i2c_dev, u8 *buf, u32 len) +{ + u32 i; + + for (i = 0; i < len; i++) + buf[i] = readb(i2c_dev->base + I2C_RX); +} + +static void sprd_i2c_set_full_thld(struct sprd_i2c *i2c_dev, u32 full_thld) +{ + u32 tmp = readl(i2c_dev->base + I2C_CTL); + + tmp &= ~FIFO_AF_LVL_MASK; + tmp |= full_thld << FIFO_AF_LVL; + writel(tmp, i2c_dev->base + I2C_CTL); +}; + +static void sprd_i2c_set_empty_thld(struct sprd_i2c *i2c_dev, u32 empty_thld) +{ + u32 tmp = readl(i2c_dev->base + I2C_CTL); + + tmp &= ~FIFO_AE_LVL_MASK; + tmp |= empty_thld << FIFO_AE_LVL; + writel(tmp, i2c_dev->base + I2C_CTL); +}; + +static void sprd_i2c_set_fifo_full_int(struct sprd_i2c *i2c_dev, int enable) +{ + u32 tmp = readl(i2c_dev->base + I2C_CTL); + + if (enable) + tmp |= FULL_INTEN; + else + tmp &= ~FULL_INTEN; + + writel(tmp, i2c_dev->base + I2C_CTL); +}; + +static void sprd_i2c_set_fifo_empty_int(struct sprd_i2c *i2c_dev, int enable) +{ + u32 tmp = readl(i2c_dev->base + I2C_CTL); + + if (enable) + tmp |= EMPTY_INTEN; + else + tmp &= ~EMPTY_INTEN; + + writel(tmp, i2c_dev->base + I2C_CTL); +}; + +static void sprd_i2c_opt_start(struct sprd_i2c *i2c_dev) +{ + u32 tmp = readl(i2c_dev->base + I2C_CTL); + + writel(tmp | I2C_START, i2c_dev->base + I2C_CTL); +} + +static void sprd_i2c_opt_mode(struct sprd_i2c *i2c_dev, int rw) +{ + u32 cmd = readl(i2c_dev->base + I2C_CTL) & ~I2C_MODE; + + writel(cmd | rw << 3, i2c_dev->base + I2C_CTL); +} + +static void sprd_i2c_data_transfer(struct sprd_i2c *i2c_dev) +{ + u32 i2c_count = i2c_dev->count; + u32 need_tran = i2c_count <= I2C_FIFO_DEEP ? i2c_count : I2C_FIFO_DEEP; + struct i2c_msg *msg = i2c_dev->msg; + + if (msg->flags & I2C_M_RD) { + sprd_i2c_read_bytes(i2c_dev, i2c_dev->buf, I2C_FIFO_FULL_THLD); + i2c_dev->count -= I2C_FIFO_FULL_THLD; + i2c_dev->buf += I2C_FIFO_FULL_THLD; + + /* + * If the read data count is larger than rx fifo full threshold, + * we should enable the rx fifo full interrupt to read data + * again. + */ + if (i2c_dev->count >= I2C_FIFO_FULL_THLD) + sprd_i2c_set_fifo_full_int(i2c_dev, 1); + } else { + sprd_i2c_write_bytes(i2c_dev, i2c_dev->buf, need_tran); + i2c_dev->buf += need_tran; + i2c_dev->count -= need_tran; + + /* + * If the write data count is arger than tx fifo depth which + * means we can not write all data in one time, then we should + * enable the tx fifo empty interrupt to write again. + */ + if (i2c_count > I2C_FIFO_DEEP) + sprd_i2c_set_fifo_empty_int(i2c_dev, 1); + } +} + +static int sprd_i2c_handle_msg(struct i2c_adapter *i2c_adap, + struct i2c_msg *msg, bool is_last_msg) +{ + struct sprd_i2c *i2c_dev = i2c_adap->algo_data; + + i2c_dev->msg = msg; + i2c_dev->buf = msg->buf; + i2c_dev->count = msg->len; + + reinit_completion(&i2c_dev->complete); + sprd_i2c_reset_fifo(i2c_dev); + sprd_i2c_set_devaddr(i2c_dev, msg); + sprd_i2c_set_count(i2c_dev, msg->len); + + if (msg->flags & I2C_M_RD) { + sprd_i2c_opt_mode(i2c_dev, 1); + sprd_i2c_send_stop(i2c_dev, 1); + } else { + sprd_i2c_opt_mode(i2c_dev, 0); + sprd_i2c_send_stop(i2c_dev, !!is_last_msg); + } + + /* + * We should enable rx fifo full interrupt to get data when receiving + * full data. + */ + if (msg->flags & I2C_M_RD) + sprd_i2c_set_fifo_full_int(i2c_dev, 1); + else + sprd_i2c_data_transfer(i2c_dev); + + sprd_i2c_opt_start(i2c_dev); + + wait_for_completion(&i2c_dev->complete); + + return i2c_dev->err; +} + +static int sprd_i2c_master_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) +{ + struct sprd_i2c *i2c_dev = i2c_adap->algo_data; + int im, ret; + + ret = pm_runtime_get_sync(i2c_dev->dev); + if (ret < 0) + return ret; + + for (im = 0; im < num - 1; im++) { + ret = sprd_i2c_handle_msg(i2c_adap, &msgs[im], 0); + if (ret) + goto err_msg; + } + + ret = sprd_i2c_handle_msg(i2c_adap, &msgs[im++], 1); + +err_msg: + pm_runtime_mark_last_busy(i2c_dev->dev); + pm_runtime_put_autosuspend(i2c_dev->dev); + + return ret < 0 ? ret : im; +} + +static u32 sprd_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm sprd_i2c_algo = { + .master_xfer = sprd_i2c_master_xfer, + .functionality = sprd_i2c_func, +}; + +static void sprd_i2c_set_clk(struct sprd_i2c *i2c_dev, u32 freq) +{ + u32 apb_clk = i2c_dev->src_clk; + /* + * From I2C databook, the prescale calculation formula: + * prescale = freq_i2c / (4 * freq_scl) - 1; + */ + u32 i2c_dvd = apb_clk / (4 * freq) - 1; + /* + * From I2C databook, the high period of SCL clock is recommended as + * 40% (2/5), and the low period of SCL clock is recommended as 60% + * (3/5), then the formula should be: + * high = (prescale * 2 * 2) / 5 + * low = (prescale * 2 * 3) / 5 + */ + u32 high = ((i2c_dvd << 1) * 2) / 5; + u32 low = ((i2c_dvd << 1) * 3) / 5; + u32 div0 = I2C_ADDR_DVD0_CALC(high, low); + u32 div1 = I2C_ADDR_DVD1_CALC(high, low); + + writel(div0, i2c_dev->base + ADDR_DVD0); + writel(div1, i2c_dev->base + ADDR_DVD1); + + /* Start hold timing = hold time(us) * source clock */ + if (freq == 400000) + writel((6 * apb_clk) / 10000000, i2c_dev->base + ADDR_STA0_DVD); + else if (freq == 100000) + writel((4 * apb_clk) / 1000000, i2c_dev->base + ADDR_STA0_DVD); +} + +static void sprd_i2c_enable(struct sprd_i2c *i2c_dev) +{ + u32 tmp = I2C_DVD_OPT; + + writel(tmp, i2c_dev->base + I2C_CTL); + + sprd_i2c_set_full_thld(i2c_dev, I2C_FIFO_FULL_THLD); + sprd_i2c_set_empty_thld(i2c_dev, I2C_FIFO_EMPTY_THLD); + + sprd_i2c_set_clk(i2c_dev, i2c_dev->bus_freq); + sprd_i2c_reset_fifo(i2c_dev); + sprd_i2c_clear_irq(i2c_dev); + + tmp = readl(i2c_dev->base + I2C_CTL); + writel(tmp | I2C_EN | I2C_INT_EN, i2c_dev->base + I2C_CTL); +} + +static irqreturn_t sprd_i2c_isr_thread(int irq, void *dev_id) +{ + struct sprd_i2c *i2c_dev = dev_id; + struct i2c_msg *msg = i2c_dev->msg; + bool ack = !(readl(i2c_dev->base + I2C_STATUS) & I2C_RX_ACK); + u32 i2c_count = readl(i2c_dev->base + I2C_COUNT); + u32 i2c_tran; + + if (msg->flags & I2C_M_RD) + i2c_tran = i2c_dev->count >= I2C_FIFO_FULL_THLD; + else + i2c_tran = i2c_count; + + /* + * If we got one ACK from slave when writing data, and we did not + * finish this transmission (i2c_tran is not zero), then we should + * continue to write data. + * + * For reading data, ack is always true, if i2c_tran is not 0 which + * means we still need to contine to read data from slave. + */ + if (i2c_tran && ack) { + sprd_i2c_data_transfer(i2c_dev); + return IRQ_HANDLED; + } + + i2c_dev->err = 0; + + /* + * If we did not get one ACK from slave when writing data, we should + * return -EIO to notify users. + */ + if (!ack) + i2c_dev->err = -EIO; + else if (msg->flags & I2C_M_RD && i2c_dev->count) + sprd_i2c_read_bytes(i2c_dev, i2c_dev->buf, i2c_dev->count); + + /* Transmission is done and clear ack and start operation */ + sprd_i2c_clear_ack(i2c_dev); + sprd_i2c_clear_start(i2c_dev); + complete(&i2c_dev->complete); + + return IRQ_HANDLED; +} + +static irqreturn_t sprd_i2c_isr(int irq, void *dev_id) +{ + struct sprd_i2c *i2c_dev = dev_id; + struct i2c_msg *msg = i2c_dev->msg; + u32 i2c_count = readl(i2c_dev->base + I2C_COUNT); + bool ack = !(readl(i2c_dev->base + I2C_STATUS) & I2C_RX_ACK); + u32 i2c_tran; + + if (msg->flags & I2C_M_RD) + i2c_tran = i2c_dev->count >= I2C_FIFO_FULL_THLD; + else + i2c_tran = i2c_count; + + /* + * If we did not get one ACK from slave when writing data, then we + * should finish this transmission since we got some errors. + * + * When writing data, if i2c_tran == 0 which means we have writen + * done all data, then we can finish this transmission. + * + * When reading data, if conut < rx fifo full threshold, which + * means we can read all data in one time, then we can finish this + * transmission too. + */ + if (!i2c_tran || !ack) { + sprd_i2c_clear_start(i2c_dev); + sprd_i2c_clear_irq(i2c_dev); + } + + sprd_i2c_set_fifo_empty_int(i2c_dev, 0); + sprd_i2c_set_fifo_full_int(i2c_dev, 0); + + return IRQ_WAKE_THREAD; +} + +static int sprd_i2c_clk_init(struct sprd_i2c *i2c_dev) +{ + struct clk *clk_i2c, *clk_parent; + + clk_i2c = devm_clk_get(i2c_dev->dev, "i2c"); + if (IS_ERR(clk_i2c)) { + dev_warn(i2c_dev->dev, "i2c%d can't get the i2c clock\n", + i2c_dev->adap.nr); + clk_i2c = NULL; + } + + clk_parent = devm_clk_get(i2c_dev->dev, "source"); + if (IS_ERR(clk_parent)) { + dev_warn(i2c_dev->dev, "i2c%d can't get the source clock\n", + i2c_dev->adap.nr); + clk_parent = NULL; + } + + if (clk_set_parent(clk_i2c, clk_parent)) + i2c_dev->src_clk = clk_get_rate(clk_i2c); + else + i2c_dev->src_clk = 26000000; + + dev_dbg(i2c_dev->dev, "i2c%d set source clock is %d\n", + i2c_dev->adap.nr, i2c_dev->src_clk); + + i2c_dev->clk = devm_clk_get(i2c_dev->dev, "enable"); + if (IS_ERR(i2c_dev->clk)) { + dev_warn(i2c_dev->dev, "i2c%d can't get the enable clock\n", + i2c_dev->adap.nr); + i2c_dev->clk = NULL; + } + + return 0; +} + +static int sprd_i2c_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct sprd_i2c *i2c_dev; + struct resource *res; + u32 prop; + int ret; + + pdev->id = of_alias_get_id(dev->of_node, "i2c"); + + i2c_dev = devm_kzalloc(dev, sizeof(struct sprd_i2c), GFP_KERNEL); + if (!i2c_dev) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + i2c_dev->base = devm_ioremap_resource(dev, res); + if (IS_ERR(i2c_dev->base)) + return PTR_ERR(i2c_dev->base); + + i2c_dev->irq = platform_get_irq(pdev, 0); + if (i2c_dev->irq < 0) { + dev_err(&pdev->dev, "failed to get irq resource\n"); + return i2c_dev->irq; + } + + i2c_set_adapdata(&i2c_dev->adap, i2c_dev); + init_completion(&i2c_dev->complete); + snprintf(i2c_dev->adap.name, sizeof(i2c_dev->adap.name), + "%s", "sprd-i2c"); + + i2c_dev->bus_freq = 100000; + i2c_dev->adap.owner = THIS_MODULE; + i2c_dev->dev = dev; + i2c_dev->adap.retries = 3; + i2c_dev->adap.algo = &sprd_i2c_algo; + i2c_dev->adap.algo_data = i2c_dev; + i2c_dev->adap.dev.parent = dev; + i2c_dev->adap.nr = pdev->id; + i2c_dev->adap.dev.of_node = dev->of_node; + + if (!of_property_read_u32(dev->of_node, "clock-frequency", &prop)) + i2c_dev->bus_freq = prop; + + /* We only support 100k and 400k now, otherwise will return error. */ + if (i2c_dev->bus_freq != 100000 && i2c_dev->bus_freq != 400000) + return -EINVAL; + + sprd_i2c_clk_init(i2c_dev); + platform_set_drvdata(pdev, i2c_dev); + + ret = clk_prepare_enable(i2c_dev->clk); + if (ret) + return ret; + + sprd_i2c_enable(i2c_dev); + + pm_runtime_set_autosuspend_delay(i2c_dev->dev, SPRD_I2C_PM_TIMEOUT); + pm_runtime_use_autosuspend(i2c_dev->dev); + pm_runtime_set_active(i2c_dev->dev); + pm_runtime_enable(i2c_dev->dev); + + ret = pm_runtime_get_sync(i2c_dev->dev); + if (ret < 0) + goto err_rpm_put; + + ret = devm_request_threaded_irq(dev, i2c_dev->irq, + sprd_i2c_isr, sprd_i2c_isr_thread, + IRQF_NO_SUSPEND | IRQF_ONESHOT, + pdev->name, i2c_dev); + if (ret) { + dev_err(&pdev->dev, "failed to request irq %d\n", i2c_dev->irq); + goto err_rpm_put; + } + + ret = i2c_add_numbered_adapter(&i2c_dev->adap); + if (ret) { + dev_err(&pdev->dev, "add adapter failed\n"); + goto err_rpm_put; + } + + pm_runtime_mark_last_busy(i2c_dev->dev); + pm_runtime_put_autosuspend(i2c_dev->dev); + return 0; + +err_rpm_put: + pm_runtime_put_noidle(i2c_dev->dev); + pm_runtime_disable(i2c_dev->dev); + clk_disable_unprepare(i2c_dev->clk); + return ret; +} + +static int sprd_i2c_remove(struct platform_device *pdev) +{ + struct sprd_i2c *i2c_dev = platform_get_drvdata(pdev); + int ret; + + ret = pm_runtime_get_sync(i2c_dev->dev); + if (ret < 0) + return ret; + + i2c_del_adapter(&i2c_dev->adap); + clk_disable_unprepare(i2c_dev->clk); + + pm_runtime_put_noidle(i2c_dev->dev); + pm_runtime_disable(i2c_dev->dev); + + return 0; +} + +static int __maybe_unused sprd_i2c_suspend_noirq(struct device *pdev) +{ + return pm_runtime_force_suspend(pdev); +} + +static int __maybe_unused sprd_i2c_resume_noirq(struct device *pdev) +{ + return pm_runtime_force_resume(pdev); +} + +static int __maybe_unused sprd_i2c_runtime_suspend(struct device *pdev) +{ + struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev); + + clk_disable_unprepare(i2c_dev->clk); + + return 0; +} + +static int __maybe_unused sprd_i2c_runtime_resume(struct device *pdev) +{ + struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev); + int ret; + + ret = clk_prepare_enable(i2c_dev->clk); + if (ret) + return ret; + + sprd_i2c_enable(i2c_dev); + + return 0; +} + +static const struct dev_pm_ops sprd_i2c_pm_ops = { + SET_RUNTIME_PM_OPS(sprd_i2c_runtime_suspend, + sprd_i2c_runtime_resume, NULL) + + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sprd_i2c_suspend_noirq, + sprd_i2c_resume_noirq) +}; + +static const struct of_device_id sprd_i2c_of_match[] = { + { .compatible = "sprd,sc9860-i2c", }, +}; + +static struct platform_driver sprd_i2c_driver = { + .probe = sprd_i2c_probe, + .remove = sprd_i2c_remove, + .driver = { + .name = "sprd-i2c", + .of_match_table = sprd_i2c_of_match, + .pm = &sprd_i2c_pm_ops, + }, +}; + +static int sprd_i2c_init(void) +{ + return platform_driver_register(&sprd_i2c_driver); +} +arch_initcall_sync(sprd_i2c_init); -- cgit v1.2.3 From ad3caf8abc385b974d863b7a7a2950f4b089fee8 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 18 Aug 2017 21:36:57 +0530 Subject: i2c: busses: make i2c_algorithm const Make these const as they are only stored in the algo field of i2c_adapter structure, which is const. Signed-off-by: Bhumika Goyal Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pnx.c | 2 +- drivers/i2c/busses/i2c-puv3.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index fd5f9d2bf6d9..42d6b3a226f8 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -590,7 +590,7 @@ static u32 i2c_pnx_func(struct i2c_adapter *adapter) return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } -static struct i2c_algorithm pnx_algorithm = { +static const struct i2c_algorithm pnx_algorithm = { .master_xfer = i2c_pnx_xfer, .functionality = i2c_pnx_func, }; diff --git a/drivers/i2c/busses/i2c-puv3.c b/drivers/i2c/busses/i2c-puv3.c index 0c8b1571886d..287088b8c4c8 100644 --- a/drivers/i2c/busses/i2c-puv3.c +++ b/drivers/i2c/busses/i2c-puv3.c @@ -175,7 +175,7 @@ static u32 puv3_i2c_func(struct i2c_adapter *adapter) return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; } -static struct i2c_algorithm puv3_i2c_algorithm = { +static const struct i2c_algorithm puv3_i2c_algorithm = { .master_xfer = puv3_i2c_xfer, .functionality = puv3_i2c_func, }; -- cgit v1.2.3 From 329430ccfc9ff864315974cf2fe7a35b00be5e9f Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 19 Aug 2017 16:04:12 +0530 Subject: i2c: busses: make i2c_adapter const Make these const as they are only used in a copy operation. Done using Coccinelle. Signed-off-by: Bhumika Goyal Acked-by: David Daney Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-kempld.c | 2 +- drivers/i2c/busses/i2c-ocores.c | 2 +- drivers/i2c/busses/i2c-octeon-platdrv.c | 2 +- drivers/i2c/busses/i2c-thunderx-pcidrv.c | 2 +- drivers/i2c/busses/i2c-xiic.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-kempld.c b/drivers/i2c/busses/i2c-kempld.c index 25993d2e64bf..e879190b5d1d 100644 --- a/drivers/i2c/busses/i2c-kempld.c +++ b/drivers/i2c/busses/i2c-kempld.c @@ -289,7 +289,7 @@ static const struct i2c_algorithm kempld_i2c_algorithm = { .functionality = kempld_i2c_func, }; -static struct i2c_adapter kempld_i2c_adapter = { +static const struct i2c_adapter kempld_i2c_adapter = { .owner = THIS_MODULE, .name = "i2c-kempld", .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index 34f1889a4073..8c42ca7107b2 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -276,7 +276,7 @@ static const struct i2c_algorithm ocores_algorithm = { .functionality = ocores_func, }; -static struct i2c_adapter ocores_adapter = { +static const struct i2c_adapter ocores_adapter = { .owner = THIS_MODULE, .name = "i2c-ocores", .class = I2C_CLASS_DEPRECATED, diff --git a/drivers/i2c/busses/i2c-octeon-platdrv.c b/drivers/i2c/busses/i2c-octeon-platdrv.c index 917524ce6890..64bda83e65ac 100644 --- a/drivers/i2c/busses/i2c-octeon-platdrv.c +++ b/drivers/i2c/busses/i2c-octeon-platdrv.c @@ -126,7 +126,7 @@ static const struct i2c_algorithm octeon_i2c_algo = { .functionality = octeon_i2c_functionality, }; -static struct i2c_adapter octeon_i2c_ops = { +static const struct i2c_adapter octeon_i2c_ops = { .owner = THIS_MODULE, .name = "OCTEON adapter", .algo = &octeon_i2c_algo, diff --git a/drivers/i2c/busses/i2c-thunderx-pcidrv.c b/drivers/i2c/busses/i2c-thunderx-pcidrv.c index ea35a895b568..df0976f4432a 100644 --- a/drivers/i2c/busses/i2c-thunderx-pcidrv.c +++ b/drivers/i2c/busses/i2c-thunderx-pcidrv.c @@ -75,7 +75,7 @@ static const struct i2c_algorithm thunderx_i2c_algo = { .functionality = thunderx_i2c_functionality, }; -static struct i2c_adapter thunderx_i2c_ops = { +static const struct i2c_adapter thunderx_i2c_ops = { .owner = THIS_MODULE, .name = "ThunderX adapter", .algo = &thunderx_i2c_algo, diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 34b27bfe72ba..ae6ed254e01d 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -721,7 +721,7 @@ static const struct i2c_algorithm xiic_algorithm = { .functionality = xiic_func, }; -static struct i2c_adapter xiic_adapter = { +static const struct i2c_adapter xiic_adapter = { .owner = THIS_MODULE, .name = DRIVER_NAME, .class = I2C_CLASS_DEPRECATED, -- cgit v1.2.3 From ae3923a284cc696311294022e9b1a49058f07387 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Mon, 21 Aug 2017 17:42:04 +0530 Subject: i2c: busses: make i2c_adapter_quirks const Make these const as they are only stored as a reference in the quirks field of an i2c_adapter structure, which is const. Done using Coccinelle. Signed-off-by: Bhumika Goyal Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-at91.c | 2 +- drivers/i2c/busses/i2c-cpm.c | 2 +- drivers/i2c/busses/i2c-mlxcpld.c | 2 +- drivers/i2c/busses/i2c-opal.c | 2 +- drivers/i2c/busses/i2c-powermac.c | 2 +- drivers/i2c/busses/i2c-qup.c | 2 +- drivers/i2c/busses/i2c-tegra.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index 38dd61d621df..bfd1fdff64a9 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -809,7 +809,7 @@ out: * The hardware can handle at most two messages concatenated by a * repeated start via it's internal address feature. */ -static struct i2c_adapter_quirks at91_twi_quirks = { +static const struct i2c_adapter_quirks at91_twi_quirks = { .flags = I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | I2C_AQ_COMB_SAME_ADDR, .max_comb_1st_msg_len = 3, }; diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index d89bde2c5da2..8a8ca945561b 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -413,7 +413,7 @@ static const struct i2c_algorithm cpm_i2c_algo = { }; /* CPM_MAX_READ is also limiting writes according to the code! */ -static struct i2c_adapter_quirks cpm_i2c_quirks = { +static const struct i2c_adapter_quirks cpm_i2c_quirks = { .max_num_msgs = CPM_MAXBD, .max_read_len = CPM_MAX_READ, .max_write_len = CPM_MAX_READ, diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c index d271e6a0954c..4c28fa28ce76 100644 --- a/drivers/i2c/busses/i2c-mlxcpld.c +++ b/drivers/i2c/busses/i2c-mlxcpld.c @@ -433,7 +433,7 @@ static const struct i2c_algorithm mlxcpld_i2c_algo = { .functionality = mlxcpld_i2c_func }; -static struct i2c_adapter_quirks mlxcpld_i2c_quirks = { +static const struct i2c_adapter_quirks mlxcpld_i2c_quirks = { .flags = I2C_AQ_COMB_WRITE_THEN_READ, .max_read_len = MLXCPLD_I2C_DATA_REG_SZ - MLXCPLD_I2C_MAX_ADDR_LEN, .max_write_len = MLXCPLD_I2C_DATA_REG_SZ, diff --git a/drivers/i2c/busses/i2c-opal.c b/drivers/i2c/busses/i2c-opal.c index 11e2a1fc10e9..0aabb7eca0c5 100644 --- a/drivers/i2c/busses/i2c-opal.c +++ b/drivers/i2c/busses/i2c-opal.c @@ -204,7 +204,7 @@ static const struct i2c_algorithm i2c_opal_algo = { * For two messages, we basically support simple smbus transactions of a * write-then-anything. */ -static struct i2c_adapter_quirks i2c_opal_quirks = { +static const struct i2c_adapter_quirks i2c_opal_quirks = { .flags = I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | I2C_AQ_COMB_SAME_ADDR, .max_comb_1st_msg_len = 4, }; diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index ef9c858fe1d4..f2a2067525ef 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -197,7 +197,7 @@ static const struct i2c_algorithm i2c_powermac_algorithm = { .functionality = i2c_powermac_func, }; -static struct i2c_adapter_quirks i2c_powermac_quirks = { +static const struct i2c_adapter_quirks i2c_powermac_quirks = { .max_num_msgs = 1, }; diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index 1902d8ac9753..08f8e0107642 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -1396,7 +1396,7 @@ static const struct i2c_algorithm qup_i2c_algo_v2 = { * the end of the read, the length of the read is specified as one byte * which limits the possible read to 256 (QUP_READ_LIMIT) bytes. */ -static struct i2c_adapter_quirks qup_i2c_quirks = { +static const struct i2c_adapter_quirks qup_i2c_quirks = { .max_read_len = QUP_READ_LIMIT, }; diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index a23884445fa2..60292d243e24 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -793,7 +793,7 @@ static const struct i2c_algorithm tegra_i2c_algo = { }; /* payload size is only 12 bit */ -static struct i2c_adapter_quirks tegra_i2c_quirks = { +static const struct i2c_adapter_quirks tegra_i2c_quirks = { .max_read_len = 4096, .max_write_len = 4096, }; -- cgit v1.2.3 From a89c22d59eee15fad0ee740308dae94668d12330 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Mon, 21 Aug 2017 18:58:37 +0530 Subject: i2c: versatile: Make i2c_algo_bit_data const Make this const as it is only used in a copy operation. Done using Coccinelle. Signed-off-by: Bhumika Goyal Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-versatile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-versatile.c b/drivers/i2c/busses/i2c-versatile.c index c73d2d22009e..f1ab2a637ec0 100644 --- a/drivers/i2c/busses/i2c-versatile.c +++ b/drivers/i2c/busses/i2c-versatile.c @@ -55,7 +55,7 @@ static int i2c_versatile_getscl(void *data) return !!(readl(i2c->base + I2C_CONTROL) & SCL); } -static struct i2c_algo_bit_data i2c_versatile_algo = { +static const struct i2c_algo_bit_data i2c_versatile_algo = { .setsda = i2c_versatile_setsda, .setscl = i2c_versatile_setscl, .getsda = i2c_versatile_getsda, -- cgit v1.2.3 From 2601a0032f0ef5a0592a8ee4e4e12bb00ec19aeb Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Wed, 23 Aug 2017 22:50:50 +0530 Subject: i2c: nomadik: constify amba_id amba_id are not supposed to change at runtime. All functions working with const amba_id. So mark the non-const structs as const. Signed-off-by: Arvind Yadav Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-nomadik.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index da6609d62848..49c7c0c91486 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -1088,7 +1088,7 @@ static struct i2c_vendor_data vendor_db8500 = { .fifodepth = 32, /* Guessed from TFTR/RFTR = 15 */ }; -static struct amba_id nmk_i2c_ids[] = { +static const struct amba_id nmk_i2c_ids[] = { { .id = 0x00180024, .mask = 0x00ffffff, -- cgit v1.2.3 From 8ce906c13c32cfd3de71063ca4b8c3b774e4ca08 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Wed, 30 Aug 2017 11:05:47 +0800 Subject: i2c: sprd: Fix undefined reference errors Since the i2c driver of Spreadtrum can not be build as one module, thus it should depend on CONFIG_I2C is build in. Signed-off-by: Baolin Wang Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 1bd3e5fc337b..f9ba983e0fb0 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -910,7 +910,7 @@ config I2C_SIRF config I2C_SPRD bool "Spreadtrum I2C interface" - depends on ARCH_SPRD + depends on I2C=y && ARCH_SPRD help If you say yes to this option, support will be included for the Spreadtrum I2C interface. -- cgit v1.2.3