diff options
Diffstat (limited to 'drivers/i2c')
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, ®); + 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, ®); + 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; |