summaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/Kconfig8
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-aspeed.c74
-rw-r--r--drivers/i2c/busses/i2c-bcm-iproc.c6
-rw-r--r--drivers/i2c/busses/i2c-cadence.c6
-rw-r--r--drivers/i2c/busses/i2c-cht-wc.c363
-rw-r--r--drivers/i2c/busses/i2c-davinci.c8
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c6
-rw-r--r--drivers/i2c/busses/i2c-designware-slave.c2
-rw-r--r--drivers/i2c/busses/i2c-exynos5.c6
-rw-r--r--drivers/i2c/busses/i2c-gpio.c4
-rw-r--r--drivers/i2c/busses/i2c-hix5hd2.c6
-rw-r--r--drivers/i2c/busses/i2c-lpc2k.c6
-rw-r--r--drivers/i2c/busses/i2c-mt65xx.c65
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c5
-rw-r--r--drivers/i2c/busses/i2c-pmcmsp.c4
-rw-r--r--drivers/i2c/busses/i2c-powermac.c10
-rw-r--r--drivers/i2c/busses/i2c-pxa.c6
-rw-r--r--drivers/i2c/busses/i2c-rcar.c5
-rw-r--r--drivers/i2c/busses/i2c-rk3x.c9
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c6
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c4
-rw-r--r--drivers/i2c/busses/i2c-sirf.c6
-rw-r--r--drivers/i2c/busses/i2c-st.c3
-rw-r--r--drivers/i2c/busses/i2c-stm32f4.c4
-rw-r--r--drivers/i2c/busses/i2c-sun6i-p2wi.c6
-rw-r--r--drivers/i2c/busses/i2c-taos-evm.c2
-rw-r--r--drivers/i2c/busses/i2c-tegra.c2
-rw-r--r--drivers/i2c/busses/i2c-uniphier-f.c46
-rw-r--r--drivers/i2c/busses/i2c-uniphier.c40
-rw-r--r--drivers/i2c/busses/i2c-xiic.c6
-rw-r--r--drivers/i2c/i2c-core-of.c24
-rw-r--r--drivers/i2c/muxes/i2c-demux-pinctrl.c4
33 files changed, 614 insertions, 139 deletions
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-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,
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-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c
new file mode 100644
index 000000000000..21312eed09e4
--- /dev/null
+++ b/drivers/i2c/busses/i2c-cht-wc.c
@@ -0,0 +1,363 @@
+/*
+ * Intel CHT Whiskey Cove PMIC I2C Master driver
+ * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
+ *
+ * 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 <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/mfd/intel_soc_pmic.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#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 adap_lock;
+ 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;
+ int read_data;
+ bool io_error;
+ 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;
+
+ mutex_lock(&adap->adap_lock);
+
+ /* Read IRQs */
+ ret = regmap_read(adap->regmap, CHT_WC_EXTCHGRIRQ, &reg);
+ if (ret) {
+ dev_err(&adap->adapter.dev, "Error reading extchgrirq reg\n");
+ mutex_unlock(&adap->adap_lock);
+ return IRQ_NONE;
+ }
+
+ 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.
+ */
+ ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, reg);
+ if (ret)
+ dev_err(&adap->adapter.dev, "Error writing extchgrirq reg\n");
+
+ if (reg & CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK) {
+ adap->io_error |= !!(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
+ * 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();
+ }
+
+ 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;
+
+ mutex_lock(&adap->adap_lock);
+ adap->io_error = false;
+ adap->done = false;
+ mutex_unlock(&adap->adap_lock);
+
+ 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;
+
+ 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);
+ if (adap->io_error)
+ ret = -EIO;
+ else if (read_write == I2C_SMBUS_READ)
+ data->byte = adap->read_data;
+ mutex_unlock(&adap->adap_lock);
+
+ return ret;
+}
+
+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, reg, 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->adap_lock);
+ 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_read(adap->regmap, CHT_WC_I2C_RDDATA, &reg);
+ if (ret)
+ return ret;
+
+ 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 <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 9e7ef5cf5d49..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,
};
@@ -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-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-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-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-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-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;
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 5c4db65c5019..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;
@@ -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-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-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-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-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;
}
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,
@@ -1158,6 +1163,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
},
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-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;
}
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-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c
index f9dd7e86b861..aceb6f788564 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,
};
@@ -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);
diff --git a/drivers/i2c/busses/i2c-sun6i-p2wi.c b/drivers/i2c/busses/i2c-sun6i-p2wi.c
index 7668e2e9b8fd..7c07ce116e38 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;
}
@@ -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);
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,
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);
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);
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);
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);
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;