diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/i2c/algos/i2c-algo-bit.c | 25 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-aspeed.c | 1 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-brcmstb.c | 13 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-cbus-gpio.c | 80 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-exynos5.c | 11 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-gpio.c | 31 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-imx.c | 37 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-iop3xx.c | 8 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-mt65xx.c | 6 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-rcar.c | 49 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-s3c2410.c | 8 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-sh_mobile.c | 121 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-sprd.c | 34 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-synquacer.c | 5 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-zx2967.c | 8 | ||||
-rw-r--r-- | drivers/i2c/i2c-core-base.c | 3 | ||||
-rw-r--r-- | drivers/i2c/i2c-core-of.c | 14 |
17 files changed, 197 insertions, 257 deletions
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index c33dcfb87993..5e5990a83da5 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -1,21 +1,12 @@ -/* ------------------------------------------------------------------------- - * i2c-algo-bit.c i2c driver algorithms for bit-shift adapters - * ------------------------------------------------------------------------- +// SPDX-License-Identifier: GPL-2.0+ +/* + * i2c-algo-bit.c: i2c driver algorithms for bit-shift adapters + * * Copyright (C) 1995-2000 Simon G. Vogl - - 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. - * ------------------------------------------------------------------------- */ - -/* With some changes from Frodo Looijaard <frodol@dds.nl>, Kyösti Mälkki - <kmalkki@cc.hut.fi> and Jean Delvare <jdelvare@suse.de> */ + * + * With some changes from Frodo Looijaard <frodol@dds.nl>, Kyösti Mälkki + * <kmalkki@cc.hut.fi> and Jean Delvare <jdelvare@suse.de> + */ #include <linux/kernel.h> #include <linux/module.h> diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index 8dc9161ced38..833b6b6a4c7e 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -930,7 +930,6 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev) init_completion(&bus->cmd_complete); bus->adap.owner = THIS_MODULE; bus->adap.retries = 0; - bus->adap.timeout = 5 * HZ; bus->adap.algo = &aspeed_i2c_algo; bus->adap.dev.parent = &pdev->dev; bus->adap.dev.of_node = pdev->dev.of_node; diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c index 826d32049996..f4d862234980 100644 --- a/drivers/i2c/busses/i2c-brcmstb.c +++ b/drivers/i2c/busses/i2c-brcmstb.c @@ -170,7 +170,6 @@ struct brcmstb_i2c_dev { struct bsc_regs *bsc_regmap; struct i2c_adapter adapter; struct completion done; - bool is_suspended; u32 clk_freq_hz; int data_regsz; }; @@ -467,9 +466,6 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter, int xfersz = brcmstb_i2c_get_xfersz(dev); u32 cond, cond_per_msg; - if (dev->is_suspended) - return -EBUSY; - /* Loop through all messages */ for (i = 0; i < num; i++) { pmsg = &msgs[i]; @@ -689,10 +685,7 @@ static int brcmstb_i2c_suspend(struct device *dev) { struct brcmstb_i2c_dev *i2c_dev = dev_get_drvdata(dev); - i2c_lock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER); - i2c_dev->is_suspended = true; - i2c_unlock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER); - + i2c_mark_adapter_suspended(&i2c_dev->adapter); return 0; } @@ -700,10 +693,8 @@ static int brcmstb_i2c_resume(struct device *dev) { struct brcmstb_i2c_dev *i2c_dev = dev_get_drvdata(dev); - i2c_lock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER); brcmstb_i2c_set_bsc_reg_defaults(i2c_dev); - i2c_dev->is_suspended = false; - i2c_unlock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER); + i2c_mark_adapter_resumed(&i2c_dev->adapter); return 0; } diff --git a/drivers/i2c/busses/i2c-cbus-gpio.c b/drivers/i2c/busses/i2c-cbus-gpio.c index b4f91e48948a..72df563477b1 100644 --- a/drivers/i2c/busses/i2c-cbus-gpio.c +++ b/drivers/i2c/busses/i2c-cbus-gpio.c @@ -18,16 +18,14 @@ #include <linux/io.h> #include <linux/i2c.h> -#include <linux/gpio.h> #include <linux/slab.h> #include <linux/delay.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_gpio.h> +#include <linux/gpio/consumer.h> #include <linux/interrupt.h> #include <linux/platform_device.h> -#include <linux/platform_data/i2c-cbus-gpio.h> /* * Bit counts are derived from Nokia implementation. These should be checked @@ -39,9 +37,9 @@ struct cbus_host { spinlock_t lock; /* host lock */ struct device *dev; - int clk_gpio; - int dat_gpio; - int sel_gpio; + struct gpio_desc *clk; + struct gpio_desc *dat; + struct gpio_desc *sel; }; /** @@ -51,9 +49,9 @@ struct cbus_host { */ static void cbus_send_bit(struct cbus_host *host, unsigned bit) { - gpio_set_value(host->dat_gpio, bit ? 1 : 0); - gpio_set_value(host->clk_gpio, 1); - gpio_set_value(host->clk_gpio, 0); + gpiod_set_value(host->dat, bit ? 1 : 0); + gpiod_set_value(host->clk, 1); + gpiod_set_value(host->clk, 0); } /** @@ -78,9 +76,9 @@ static int cbus_receive_bit(struct cbus_host *host) { int ret; - gpio_set_value(host->clk_gpio, 1); - ret = gpio_get_value(host->dat_gpio); - gpio_set_value(host->clk_gpio, 0); + gpiod_set_value(host->clk, 1); + ret = gpiod_get_value(host->dat); + gpiod_set_value(host->clk, 0); return ret; } @@ -123,10 +121,10 @@ static int cbus_transfer(struct cbus_host *host, char rw, unsigned dev, spin_lock_irqsave(&host->lock, flags); /* Reset state and start of transfer, SEL stays down during transfer */ - gpio_set_value(host->sel_gpio, 0); + gpiod_set_value(host->sel, 0); /* Set the DAT pin to output */ - gpio_direction_output(host->dat_gpio, 1); + gpiod_direction_output(host->dat, 1); /* Send the device address */ cbus_send_data(host, dev, CBUS_ADDR_BITS); @@ -141,12 +139,12 @@ static int cbus_transfer(struct cbus_host *host, char rw, unsigned dev, cbus_send_data(host, data, 16); ret = 0; } else { - ret = gpio_direction_input(host->dat_gpio); + ret = gpiod_direction_input(host->dat); if (ret) { dev_dbg(host->dev, "failed setting direction\n"); goto out; } - gpio_set_value(host->clk_gpio, 1); + gpiod_set_value(host->clk, 1); ret = cbus_receive_word(host); if (ret < 0) { @@ -156,9 +154,9 @@ static int cbus_transfer(struct cbus_host *host, char rw, unsigned dev, } /* Indicate end of transfer, SEL goes up until next transfer */ - gpio_set_value(host->sel_gpio, 1); - gpio_set_value(host->clk_gpio, 1); - gpio_set_value(host->clk_gpio, 0); + gpiod_set_value(host->sel, 1); + gpiod_set_value(host->clk, 1); + gpiod_set_value(host->clk, 0); out: spin_unlock_irqrestore(&host->lock, flags); @@ -214,7 +212,6 @@ static int cbus_i2c_probe(struct platform_device *pdev) { struct i2c_adapter *adapter; struct cbus_host *chost; - int ret; adapter = devm_kzalloc(&pdev->dev, sizeof(struct i2c_adapter), GFP_KERNEL); @@ -225,22 +222,20 @@ static int cbus_i2c_probe(struct platform_device *pdev) if (!chost) return -ENOMEM; - if (pdev->dev.of_node) { - struct device_node *dnode = pdev->dev.of_node; - if (of_gpio_count(dnode) != 3) - return -ENODEV; - chost->clk_gpio = of_get_gpio(dnode, 0); - chost->dat_gpio = of_get_gpio(dnode, 1); - chost->sel_gpio = of_get_gpio(dnode, 2); - } else if (dev_get_platdata(&pdev->dev)) { - struct i2c_cbus_platform_data *pdata = - dev_get_platdata(&pdev->dev); - chost->clk_gpio = pdata->clk_gpio; - chost->dat_gpio = pdata->dat_gpio; - chost->sel_gpio = pdata->sel_gpio; - } else { + if (gpiod_count(&pdev->dev, NULL) != 3) return -ENODEV; - } + chost->clk = devm_gpiod_get_index(&pdev->dev, NULL, 0, GPIOD_OUT_LOW); + if (IS_ERR(chost->clk)) + return PTR_ERR(chost->clk); + chost->dat = devm_gpiod_get_index(&pdev->dev, NULL, 1, GPIOD_IN); + if (IS_ERR(chost->dat)) + return PTR_ERR(chost->dat); + chost->sel = devm_gpiod_get_index(&pdev->dev, NULL, 2, GPIOD_OUT_HIGH); + if (IS_ERR(chost->sel)) + return PTR_ERR(chost->sel); + gpiod_set_consumer_name(chost->clk, "CBUS clk"); + gpiod_set_consumer_name(chost->dat, "CBUS dat"); + gpiod_set_consumer_name(chost->sel, "CBUS sel"); adapter->owner = THIS_MODULE; adapter->class = I2C_CLASS_HWMON; @@ -254,21 +249,6 @@ static int cbus_i2c_probe(struct platform_device *pdev) spin_lock_init(&chost->lock); chost->dev = &pdev->dev; - ret = devm_gpio_request_one(&pdev->dev, chost->clk_gpio, - GPIOF_OUT_INIT_LOW, "CBUS clk"); - if (ret) - return ret; - - ret = devm_gpio_request_one(&pdev->dev, chost->dat_gpio, GPIOF_IN, - "CBUS data"); - if (ret) - return ret; - - ret = devm_gpio_request_one(&pdev->dev, chost->sel_gpio, - GPIOF_OUT_INIT_HIGH, "CBUS sel"); - if (ret) - return ret; - i2c_set_adapdata(adapter, chost); platform_set_drvdata(pdev, adapter); diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index c1ce2299a76e..41de4ee409b6 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -183,7 +183,6 @@ enum i2c_type_exynos { struct exynos5_i2c { struct i2c_adapter adap; - unsigned int suspended:1; struct i2c_msg *msg; struct completion msg_complete; @@ -715,11 +714,6 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap, struct exynos5_i2c *i2c = adap->algo_data; int i, ret; - if (i2c->suspended) { - dev_err(i2c->dev, "HS-I2C is not initialized.\n"); - return -EIO; - } - ret = clk_enable(i2c->clk); if (ret) return ret; @@ -847,8 +841,7 @@ static int exynos5_i2c_suspend_noirq(struct device *dev) { struct exynos5_i2c *i2c = dev_get_drvdata(dev); - i2c->suspended = 1; - + i2c_mark_adapter_suspended(&i2c->adap); clk_unprepare(i2c->clk); return 0; @@ -871,7 +864,7 @@ static int exynos5_i2c_resume_noirq(struct device *dev) exynos5_i2c_init(i2c); clk_disable(i2c->clk); - i2c->suspended = 0; + i2c_mark_adapter_resumed(&i2c->adap); return 0; } diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index c008d209f0b8..2d532cc042f5 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -9,15 +9,15 @@ */ #include <linux/debugfs.h> #include <linux/delay.h> -#include <linux/i2c.h> +#include <linux/gpio/consumer.h> #include <linux/i2c-algo-bit.h> -#include <linux/platform_data/i2c-gpio.h> +#include <linux/i2c.h> #include <linux/init.h> #include <linux/module.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/gpio/consumer.h> #include <linux/of.h> +#include <linux/platform_data/i2c-gpio.h> +#include <linux/platform_device.h> +#include <linux/slab.h> struct i2c_gpio_private_data { struct gpio_desc *sda; @@ -181,12 +181,12 @@ static void i2c_gpio_fault_injector_init(struct platform_device *pdev) if (!priv->debug_dir) return; - debugfs_create_file_unsafe("scl", 0600, priv->debug_dir, priv, &fops_scl); - debugfs_create_file_unsafe("sda", 0600, priv->debug_dir, priv, &fops_sda); debugfs_create_file_unsafe("incomplete_address_phase", 0200, priv->debug_dir, priv, &fops_incomplete_addr_phase); debugfs_create_file_unsafe("incomplete_write_byte", 0200, priv->debug_dir, priv, &fops_incomplete_write_byte); + debugfs_create_file_unsafe("scl", 0600, priv->debug_dir, priv, &fops_scl); + debugfs_create_file_unsafe("sda", 0600, priv->debug_dir, priv, &fops_sda); } static void i2c_gpio_fault_injector_exit(struct platform_device *pdev) @@ -286,11 +286,11 @@ static int i2c_gpio_probe(struct platform_device *pdev) /* * First get the GPIO pins; if it fails, we'll defer the probe. - * If the SDA line is marked from platform data or device tree as - * "open drain" it means something outside of our control is making - * this line being handled as open drain, and we should just handle - * it as any other output. Else we enforce open drain as this is - * required for an I2C bus. + * If the SCL/SDA lines are marked "open drain" by platform data or + * device tree then this means that something outside of our control is + * marking these lines to be handled as open drain, and we should just + * handle them as we handle any other output. Else we enforce open + * drain as this is required for an I2C bus. */ if (pdata->sda_is_open_drain) gflags = GPIOD_OUT_HIGH; @@ -300,13 +300,6 @@ static int i2c_gpio_probe(struct platform_device *pdev) if (IS_ERR(priv->sda)) return PTR_ERR(priv->sda); - /* - * If the SCL line is marked from platform data or device tree as - * "open drain" it means something outside of our control is making - * this line being handled as open drain, and we should just handle - * it as any other output. Else we enforce open drain as this is - * required for an I2C bus. - */ if (pdata->scl_is_open_drain) gflags = GPIOD_OUT_HIGH; else diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index fa9ad53845d9..42fed40198a0 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -273,8 +273,8 @@ static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx, } /* Functions for DMA support */ -static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, - dma_addr_t phy_addr) +static int i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, + dma_addr_t phy_addr) { struct imx_i2c_dma *dma; struct dma_slave_config dma_sconfig; @@ -283,11 +283,13 @@ static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL); if (!dma) - return; + return -ENOMEM; - dma->chan_tx = dma_request_slave_channel(dev, "tx"); - if (!dma->chan_tx) { - dev_dbg(dev, "can't request DMA tx channel\n"); + dma->chan_tx = dma_request_chan(dev, "tx"); + if (IS_ERR(dma->chan_tx)) { + ret = PTR_ERR(dma->chan_tx); + if (ret != -ENODEV && ret != -EPROBE_DEFER) + dev_err(dev, "can't request DMA tx channel (%d)\n", ret); goto fail_al; } @@ -298,13 +300,15 @@ static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, dma_sconfig.direction = DMA_MEM_TO_DEV; ret = dmaengine_slave_config(dma->chan_tx, &dma_sconfig); if (ret < 0) { - dev_dbg(dev, "can't configure tx channel\n"); + dev_err(dev, "can't configure tx channel (%d)\n", ret); goto fail_tx; } - dma->chan_rx = dma_request_slave_channel(dev, "rx"); - if (!dma->chan_rx) { - dev_dbg(dev, "can't request DMA rx channel\n"); + dma->chan_rx = dma_request_chan(dev, "rx"); + if (IS_ERR(dma->chan_rx)) { + ret = PTR_ERR(dma->chan_rx); + if (ret != -ENODEV && ret != -EPROBE_DEFER) + dev_err(dev, "can't request DMA rx channel (%d)\n", ret); goto fail_tx; } @@ -315,7 +319,7 @@ static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, dma_sconfig.direction = DMA_DEV_TO_MEM; ret = dmaengine_slave_config(dma->chan_rx, &dma_sconfig); if (ret < 0) { - dev_dbg(dev, "can't configure rx channel\n"); + dev_err(dev, "can't configure rx channel (%d)\n", ret); goto fail_rx; } @@ -324,7 +328,7 @@ static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, dev_info(dev, "using %s (tx) and %s (rx) for DMA transfers\n", dma_chan_name(dma->chan_tx), dma_chan_name(dma->chan_rx)); - return; + return 0; fail_rx: dma_release_channel(dma->chan_rx); @@ -332,7 +336,8 @@ fail_tx: dma_release_channel(dma->chan_tx); fail_al: devm_kfree(dev, dma); - dev_info(dev, "can't use DMA, using PIO instead.\n"); + /* return successfully if there is no dma support */ + return ret == -ENODEV ? 0 : ret; } static void i2c_imx_dma_callback(void *arg) @@ -1160,11 +1165,13 @@ static int i2c_imx_probe(struct platform_device *pdev) dev_dbg(&i2c_imx->adapter.dev, "device resources: %pR\n", res); dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n", i2c_imx->adapter.name); - dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n"); /* Init DMA config if supported */ - i2c_imx_dma_request(i2c_imx, phy_addr); + ret = i2c_imx_dma_request(i2c_imx, phy_addr); + if (ret < 0) + goto clk_notifier_unregister; + dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n"); return 0; /* Return OK */ clk_notifier_unregister: diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c index 85cbe4b55578..a34cb3848280 100644 --- a/drivers/i2c/busses/i2c-iop3xx.c +++ b/drivers/i2c/busses/i2c-iop3xx.c @@ -471,6 +471,7 @@ iop3xx_i2c_probe(struct platform_device *pdev) new_adapter->owner = THIS_MODULE; new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; new_adapter->dev.parent = &pdev->dev; + new_adapter->dev.of_node = pdev->dev.of_node; new_adapter->nr = pdev->id; /* @@ -508,12 +509,19 @@ out: return ret; } +static const struct of_device_id i2c_iop3xx_match[] = { + { .compatible = "intel,iop3xx-i2c", }, + { .compatible = "intel,ixp4xx-i2c", }, + {}, +}; +MODULE_DEVICE_TABLE(of, i2c_iop3xx_match); static struct platform_driver iop3xx_i2c_driver = { .probe = iop3xx_i2c_probe, .remove = iop3xx_i2c_remove, .driver = { .name = "IOP3xx-I2C", + .of_match_table = i2c_iop3xx_match, }, }; diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index a74ef76705e0..660de1ee68ed 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -456,7 +456,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, control_reg = readw(i2c->base + OFFSET_CONTROL) & ~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS); - if ((i2c->speed_hz > 400000) || (left_num >= 1)) + if ((i2c->speed_hz > MAX_FS_MODE_SPEED) || (left_num >= 1)) control_reg |= I2C_CONTROL_RS; if (i2c->op == I2C_MASTER_WRRD) @@ -465,7 +465,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, writew(control_reg, i2c->base + OFFSET_CONTROL); /* set start condition */ - if (i2c->speed_hz <= 100000) + if (i2c->speed_hz <= I2C_DEFAULT_SPEED) writew(I2C_ST_START_CON, i2c->base + OFFSET_EXT_CONF); else writew(I2C_FS_START_CON, i2c->base + OFFSET_EXT_CONF); @@ -642,8 +642,6 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, return -ETIMEDOUT; } - completion_done(&i2c->msg_complete); - if (i2c->irq_stat & (I2C_HS_NACKERR | I2C_ACKERR)) { dev_dbg(i2c->dev, "addr: %x, transfer ACK error\n", msgs->addr); mtk_i2c_init_hw(i2c); diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 254e6219e538..dd52a068b140 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -2,8 +2,8 @@ /* * Driver for the Renesas R-Car I2C unit * - * Copyright (C) 2014-15 Wolfram Sang <wsa@sang-engineering.com> - * Copyright (C) 2011-2015 Renesas Electronics Corporation + * Copyright (C) 2014-19 Wolfram Sang <wsa@sang-engineering.com> + * Copyright (C) 2011-2019 Renesas Electronics Corporation * * Copyright (C) 2012-14 Renesas Solutions Corp. * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> @@ -39,8 +39,8 @@ #define ICSAR 0x1C /* slave address */ #define ICMAR 0x20 /* master address */ #define ICRXTX 0x24 /* data port */ -#define ICDMAER 0x3c /* DMA enable */ -#define ICFBSCR 0x38 /* first bit setup cycle */ +#define ICFBSCR 0x38 /* first bit setup cycle (Gen3) */ +#define ICDMAER 0x3c /* DMA enable (Gen3) */ /* ICSCR */ #define SDBS (1 << 3) /* slave data buffer select */ @@ -83,7 +83,6 @@ #define TMDMAE (1 << 0) /* DMA Master Transmitted Enable */ /* ICFBSCR */ -#define TCYC06 0x04 /* 6*Tcyc delay 1st bit between SDA and SCL */ #define TCYC17 0x0f /* 17*Tcyc delay 1st bit between SDA and SCL */ @@ -212,6 +211,10 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv) rcar_i2c_write(priv, ICMSR, 0); /* start clock */ rcar_i2c_write(priv, ICCCR, priv->icccr); + + if (priv->devtype == I2C_RCAR_GEN3) + rcar_i2c_write(priv, ICFBSCR, TCYC17); + } static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv) @@ -355,9 +358,6 @@ static void rcar_i2c_next_msg(struct rcar_i2c_priv *priv) rcar_i2c_prepare_msg(priv); } -/* - * interrupt functions - */ static void rcar_i2c_dma_unmap(struct rcar_i2c_priv *priv) { struct dma_chan *chan = priv->dma_direction == DMA_FROM_DEVICE @@ -366,9 +366,6 @@ static void rcar_i2c_dma_unmap(struct rcar_i2c_priv *priv) /* Disable DMA Master Received/Transmitted */ rcar_i2c_write(priv, ICDMAER, 0); - /* Reset default delay */ - rcar_i2c_write(priv, ICFBSCR, TCYC06); - dma_unmap_single(chan->device->dev, sg_dma_address(&priv->sg), sg_dma_len(&priv->sg), priv->dma_direction); @@ -464,9 +461,6 @@ static void rcar_i2c_dma(struct rcar_i2c_priv *priv) return; } - /* Set delay for DMA operations */ - rcar_i2c_write(priv, ICFBSCR, TCYC17); - /* Enable DMA Master Received/Transmitted */ if (read) rcar_i2c_write(priv, ICDMAER, RMDMAE); @@ -1017,10 +1011,37 @@ static int rcar_i2c_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int rcar_i2c_suspend(struct device *dev) +{ + struct rcar_i2c_priv *priv = dev_get_drvdata(dev); + + i2c_mark_adapter_suspended(&priv->adap); + return 0; +} + +static int rcar_i2c_resume(struct device *dev) +{ + struct rcar_i2c_priv *priv = dev_get_drvdata(dev); + + i2c_mark_adapter_resumed(&priv->adap); + return 0; +} + +static const struct dev_pm_ops rcar_i2c_pm_ops = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(rcar_i2c_suspend, rcar_i2c_resume) +}; + +#define DEV_PM_OPS (&rcar_i2c_pm_ops) +#else +#define DEV_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ + static struct platform_driver rcar_i2c_driver = { .driver = { .name = "i2c-rcar", .of_match_table = rcar_i2c_dt_ids, + .pm = DEV_PM_OPS, }, .probe = rcar_i2c_probe, .remove = rcar_i2c_remove, diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 2f2e28d60ef5..53bc021f4a5a 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -104,7 +104,6 @@ enum s3c24xx_i2c_state { struct s3c24xx_i2c { wait_queue_head_t wait; kernel_ulong_t quirks; - unsigned int suspended:1; struct i2c_msg *msg; unsigned int msg_num; @@ -703,9 +702,6 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, unsigned long timeout; int ret; - if (i2c->suspended) - return -EIO; - ret = s3c24xx_i2c_set_master(i2c); if (ret != 0) { dev_err(i2c->dev, "cannot get bus (error %d)\n", ret); @@ -1246,7 +1242,7 @@ static int s3c24xx_i2c_suspend_noirq(struct device *dev) { struct s3c24xx_i2c *i2c = dev_get_drvdata(dev); - i2c->suspended = 1; + i2c_mark_adapter_suspended(&i2c->adap); if (!IS_ERR(i2c->sysreg)) regmap_read(i2c->sysreg, EXYNOS5_SYS_I2C_CFG, &i2c->sys_i2c_cfg); @@ -1267,7 +1263,7 @@ static int s3c24xx_i2c_resume_noirq(struct device *dev) return ret; s3c24xx_i2c_init(i2c); clk_disable(i2c->clk); - i2c->suspended = 0; + i2c_mark_adapter_resumed(&i2c->adap); return 0; } diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index a64f2ff3cb49..8777af4c695e 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -2,8 +2,7 @@ /* * SuperH Mobile I2C Controller * - * Copyright (C) 2014 Wolfram Sang <wsa@sang-engineering.com> - * + * Copyright (C) 2014-19 Wolfram Sang <wsa@sang-engineering.com> * Copyright (C) 2008 Magnus Damm * * Portions of the code based on out-of-tree driver i2c-sh7343.c @@ -303,13 +302,12 @@ static int sh_mobile_i2c_v2_init(struct sh_mobile_i2c_data *pd) return sh_mobile_i2c_check_timing(pd); } -static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, - enum sh_mobile_i2c_op op, unsigned char data) +static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, enum sh_mobile_i2c_op op) { unsigned char ret = 0; unsigned long flags; - dev_dbg(pd->dev, "op %d, data in 0x%02x\n", op, data); + dev_dbg(pd->dev, "op %d\n", op); spin_lock_irqsave(&pd->lock, flags); @@ -317,12 +315,12 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, case OP_START: /* issue start and trigger DTE interrupt */ iic_wr(pd, ICCR, ICCR_ICE | ICCR_TRS | ICCR_BBSY); break; - case OP_TX_FIRST: /* disable DTE interrupt and write data */ + case OP_TX_FIRST: /* disable DTE interrupt and write client address */ iic_wr(pd, ICIC, ICIC_WAITE | ICIC_ALE | ICIC_TACKE); - iic_wr(pd, ICDR, data); + iic_wr(pd, ICDR, i2c_8bit_addr_from_msg(pd->msg)); break; case OP_TX: /* write data */ - iic_wr(pd, ICDR, data); + iic_wr(pd, ICDR, pd->msg->buf[pd->pos]); break; case OP_TX_STOP: /* issue a stop (or rep_start) */ iic_wr(pd, ICCR, pd->send_stop ? ICCR_ICE | ICCR_TRS @@ -353,34 +351,17 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, return ret; } -static bool sh_mobile_i2c_is_first_byte(struct sh_mobile_i2c_data *pd) -{ - return pd->pos == -1; -} - -static void sh_mobile_i2c_get_data(struct sh_mobile_i2c_data *pd, - unsigned char *buf) -{ - switch (pd->pos) { - case -1: - *buf = i2c_8bit_addr_from_msg(pd->msg); - break; - default: - *buf = pd->msg->buf[pd->pos]; - } -} - static int sh_mobile_i2c_isr_tx(struct sh_mobile_i2c_data *pd) { - unsigned char data; - if (pd->pos == pd->msg->len) { - i2c_op(pd, OP_TX_STOP, 0); + i2c_op(pd, OP_TX_STOP); return 1; } - sh_mobile_i2c_get_data(pd, &data); - i2c_op(pd, sh_mobile_i2c_is_first_byte(pd) ? OP_TX_FIRST : OP_TX, data); + if (pd->pos == -1) + i2c_op(pd, OP_TX_FIRST); + else + i2c_op(pd, OP_TX); pd->pos++; return 0; @@ -391,45 +372,32 @@ static int sh_mobile_i2c_isr_rx(struct sh_mobile_i2c_data *pd) unsigned char data; int real_pos; - do { - if (pd->pos <= -1) { - sh_mobile_i2c_get_data(pd, &data); - - if (sh_mobile_i2c_is_first_byte(pd)) - i2c_op(pd, OP_TX_FIRST, data); - else - i2c_op(pd, OP_TX, data); - break; - } - - if (pd->pos == 0) { - i2c_op(pd, OP_TX_TO_RX, 0); - break; - } - - real_pos = pd->pos - 2; - - if (pd->pos == pd->msg->len) { - if (pd->stop_after_dma) { - /* Simulate PIO end condition after DMA transfer */ - i2c_op(pd, OP_RX_STOP, 0); - pd->pos++; - break; - } - - if (real_pos < 0) { - i2c_op(pd, OP_RX_STOP, 0); - break; - } - data = i2c_op(pd, OP_RX_STOP_DATA, 0); - } else if (real_pos >= 0) { - data = i2c_op(pd, OP_RX, 0); + /* switch from TX (address) to RX (data) adds two interrupts */ + real_pos = pd->pos - 2; + + if (pd->pos == -1) { + i2c_op(pd, OP_TX_FIRST); + } else if (pd->pos == 0) { + i2c_op(pd, OP_TX_TO_RX); + } else if (pd->pos == pd->msg->len) { + if (pd->stop_after_dma) { + /* Simulate PIO end condition after DMA transfer */ + i2c_op(pd, OP_RX_STOP); + pd->pos++; + goto done; } - if (real_pos >= 0) - pd->msg->buf[real_pos] = data; - } while (0); + if (real_pos < 0) + i2c_op(pd, OP_RX_STOP); + else + data = i2c_op(pd, OP_RX_STOP_DATA); + } else if (real_pos >= 0) { + data = i2c_op(pd, OP_RX); + } + if (real_pos >= 0) + pd->msg->buf[real_pos] = data; + done: pd->pos++; return pd->pos == (pd->msg->len + 2); } @@ -698,7 +666,7 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, start_ch(pd, msg, do_start); if (do_start) - i2c_op(pd, OP_START, 0); + i2c_op(pd, OP_START); /* The interrupt handler takes care of the rest... */ timeout = wait_event_timeout(pd->wait, @@ -749,8 +717,7 @@ static const struct i2c_adapter_quirks sh_mobile_i2c_quirks = { }; /* - * r8a7740 chip has lasting errata on I2C I/O pad reset. - * this is work-around for it. + * r8a7740 has an errata regarding I2C I/O pad reset needing this workaround. */ static int sh_mobile_i2c_r8a7740_workaround(struct sh_mobile_i2c_data *pd) { @@ -802,15 +769,15 @@ static const struct of_device_id sh_mobile_i2c_dt_ids[] = { { .compatible = "renesas,iic-r8a7740", .data = &r8a7740_dt_config }, { .compatible = "renesas,iic-r8a774c0", .data = &fast_clock_dt_config }, { .compatible = "renesas,iic-r8a7790", .data = &v2_freq_calc_dt_config }, - { .compatible = "renesas,iic-r8a7791", .data = &fast_clock_dt_config }, - { .compatible = "renesas,iic-r8a7792", .data = &fast_clock_dt_config }, - { .compatible = "renesas,iic-r8a7793", .data = &fast_clock_dt_config }, - { .compatible = "renesas,iic-r8a7794", .data = &fast_clock_dt_config }, - { .compatible = "renesas,rcar-gen2-iic", .data = &fast_clock_dt_config }, - { .compatible = "renesas,iic-r8a7795", .data = &fast_clock_dt_config }, - { .compatible = "renesas,rcar-gen3-iic", .data = &fast_clock_dt_config }, - { .compatible = "renesas,iic-r8a77990", .data = &fast_clock_dt_config }, + { .compatible = "renesas,iic-r8a7791", .data = &v2_freq_calc_dt_config }, + { .compatible = "renesas,iic-r8a7792", .data = &v2_freq_calc_dt_config }, + { .compatible = "renesas,iic-r8a7793", .data = &v2_freq_calc_dt_config }, + { .compatible = "renesas,iic-r8a7794", .data = &v2_freq_calc_dt_config }, + { .compatible = "renesas,iic-r8a7795", .data = &v2_freq_calc_dt_config }, + { .compatible = "renesas,iic-r8a77990", .data = &v2_freq_calc_dt_config }, { .compatible = "renesas,iic-sh73a0", .data = &fast_clock_dt_config }, + { .compatible = "renesas,rcar-gen2-iic", .data = &v2_freq_calc_dt_config }, + { .compatible = "renesas,rcar-gen3-iic", .data = &v2_freq_calc_dt_config }, { .compatible = "renesas,rmobile-iic", .data = &default_dt_config }, {}, }; diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c index a94e724f51dc..961123529678 100644 --- a/drivers/i2c/busses/i2c-sprd.c +++ b/drivers/i2c/busses/i2c-sprd.c @@ -86,7 +86,6 @@ struct sprd_i2c { u32 count; int irq; int err; - bool is_suspended; }; static void sprd_i2c_set_count(struct sprd_i2c *i2c_dev, u32 count) @@ -284,9 +283,6 @@ static int sprd_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct sprd_i2c *i2c_dev = i2c_adap->algo_data; int im, ret; - if (i2c_dev->is_suspended) - return -EBUSY; - ret = pm_runtime_get_sync(i2c_dev->dev); if (ret < 0) return ret; @@ -586,40 +582,34 @@ static int sprd_i2c_remove(struct platform_device *pdev) return 0; } -static int __maybe_unused sprd_i2c_suspend_noirq(struct device *pdev) +static int __maybe_unused sprd_i2c_suspend_noirq(struct device *dev) { - struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev); - - i2c_lock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER); - i2c_dev->is_suspended = true; - i2c_unlock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER); + struct sprd_i2c *i2c_dev = dev_get_drvdata(dev); - return pm_runtime_force_suspend(pdev); + i2c_mark_adapter_suspended(&i2c_dev->adap); + return pm_runtime_force_suspend(dev); } -static int __maybe_unused sprd_i2c_resume_noirq(struct device *pdev) +static int __maybe_unused sprd_i2c_resume_noirq(struct device *dev) { - struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev); - - i2c_lock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER); - i2c_dev->is_suspended = false; - i2c_unlock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER); + struct sprd_i2c *i2c_dev = dev_get_drvdata(dev); - return pm_runtime_force_resume(pdev); + i2c_mark_adapter_resumed(&i2c_dev->adap); + return pm_runtime_force_resume(dev); } -static int __maybe_unused sprd_i2c_runtime_suspend(struct device *pdev) +static int __maybe_unused sprd_i2c_runtime_suspend(struct device *dev) { - struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev); + struct sprd_i2c *i2c_dev = dev_get_drvdata(dev); clk_disable_unprepare(i2c_dev->clk); return 0; } -static int __maybe_unused sprd_i2c_runtime_resume(struct device *pdev) +static int __maybe_unused sprd_i2c_runtime_resume(struct device *dev) { - struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev); + struct sprd_i2c *i2c_dev = dev_get_drvdata(dev); int ret; ret = clk_prepare_enable(i2c_dev->clk); diff --git a/drivers/i2c/busses/i2c-synquacer.c b/drivers/i2c/busses/i2c-synquacer.c index 2184b7c3580e..d18b0941b71a 100644 --- a/drivers/i2c/busses/i2c-synquacer.c +++ b/drivers/i2c/busses/i2c-synquacer.c @@ -144,8 +144,6 @@ struct synquacer_i2c { u32 timeout_ms; enum i2c_state state; struct i2c_adapter adapter; - - bool is_suspended; }; static inline int is_lastmsg(struct synquacer_i2c *i2c) @@ -316,9 +314,6 @@ static int synquacer_i2c_doxfer(struct synquacer_i2c *i2c, unsigned long timeout; int ret; - if (i2c->is_suspended) - return -EBUSY; - synquacer_i2c_hw_init(i2c); bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR); if (bsr & SYNQUACER_I2C_BSR_BB) { diff --git a/drivers/i2c/busses/i2c-zx2967.c b/drivers/i2c/busses/i2c-zx2967.c index b8f9e020d80e..7b98d97da3c6 100644 --- a/drivers/i2c/busses/i2c-zx2967.c +++ b/drivers/i2c/busses/i2c-zx2967.c @@ -66,7 +66,6 @@ struct zx2967_i2c { int msg_rd; u8 *cur_trans; u8 access_cnt; - bool is_suspended; int error; }; @@ -313,9 +312,6 @@ static int zx2967_i2c_xfer(struct i2c_adapter *adap, int ret; int i; - if (i2c->is_suspended) - return -EBUSY; - zx2967_set_addr(i2c, msgs->addr); for (i = 0; i < num; i++) { @@ -470,7 +466,7 @@ static int __maybe_unused zx2967_i2c_suspend(struct device *dev) { struct zx2967_i2c *i2c = dev_get_drvdata(dev); - i2c->is_suspended = true; + i2c_mark_adapter_suspended(&i2c->adap); clk_disable_unprepare(i2c->clk); return 0; @@ -480,8 +476,8 @@ static int __maybe_unused zx2967_i2c_resume(struct device *dev) { struct zx2967_i2c *i2c = dev_get_drvdata(dev); - i2c->is_suspended = false; clk_prepare_enable(i2c->clk); + i2c_mark_adapter_resumed(&i2c->adap); return 0; } diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 28460f6a60cc..926ca0a7477f 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -1232,6 +1232,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap) if (!adap->lock_ops) adap->lock_ops = &i2c_adapter_lock_ops; + adap->locked_flags = 0; rt_mutex_init(&adap->bus_lock); rt_mutex_init(&adap->mux_lock); mutex_init(&adap->userspace_clients_lock); @@ -1865,6 +1866,8 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) if (WARN_ON(!msgs || num < 1)) return -EINVAL; + if (WARN_ON(test_bit(I2C_ALF_IS_SUSPENDED, &adap->locked_flags))) + return -ESHUTDOWN; if (adap->quirks && i2c_check_for_quirks(adap, msgs, num)) return -EOPNOTSUPP; diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c index 6cb7ad608bcd..0f01cdba9d2c 100644 --- a/drivers/i2c/i2c-core-of.c +++ b/drivers/i2c/i2c-core-of.c @@ -121,6 +121,17 @@ static int of_dev_node_match(struct device *dev, void *data) return dev->of_node == data; } +static int of_dev_or_parent_node_match(struct device *dev, void *data) +{ + if (dev->of_node == data) + return 1; + + if (dev->parent) + return dev->parent->of_node == data; + + return 0; +} + /* must call put_device() when done with returned i2c_client device */ struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) { @@ -145,7 +156,8 @@ struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node) struct device *dev; struct i2c_adapter *adapter; - dev = bus_find_device(&i2c_bus_type, NULL, node, of_dev_node_match); + dev = bus_find_device(&i2c_bus_type, NULL, node, + of_dev_or_parent_node_match); if (!dev) return NULL; |