summaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-03 12:18:47 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-03 12:18:47 -0700
commit14b730723aac9cf3ba0a74e830491e9a43bfc80a (patch)
tree2d1591012ce62103a8c9fa0ebc4d002408f4d47f /drivers/i2c
parentd26f552ebbfb0f2c7fe712f457a038d60ed73daa (diff)
parent889ef45cd4b64cc4fd6dbebecddb8ea4df8cc1e7 (diff)
Merge branch 'i2c/for-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wilfram Sang: "I2C has the following updates for you: - an immutable cross-subsystem branch fixing PMIC access on Intel Baytrail - bigger driver updates to the designware, meson, exynos5 drivers - new i2c_acpi_new_device() function to create devices from ACPI - struct i2c_driver has now a flag 'disable_i2c_core_irq_mapping' to allow custom IRQ mapping in case the default does not fit - mux subsystem centralized error messages in its core - new driver for ltc4306 i2c mux - usual set of small updates" * 'i2c/for-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (44 commits) i2c: thunderx: Enable HWMON class probing i2c: rcar: clarify PM handling with more comments i2c: rcar: fix resume by always initializing registers before transfer i2c: tegra: fix spelling mistake: "contoller" -> "controller" i2c: exynos5: use core helper to get driver data i2c: exynos5: de-duplicate error logs on clock setup i2c: exynos5: simplify clock frequency handling i2c: exynos5: simplify timings calculation i2c: designware-baytrail: fix potential null pointer dereference on dev i2c: designware: Get selected speed mode sda-hold-time via ACPI [media] cx231xx: stop double error reporting i2c: core: Allow drivers to disable i2c-core irq mapping i2c: core: Add new i2c_acpi_new_device helper function i2c: core: Allow getting ACPI info by index i2c: img-scb: use setup_timer i2c: i2c-scmi: add a MS HID i2c: mux: ltc4306: LTC4306 and LTC4305 I2C multiplexer/switch dt-bindings: i2c: mux: ltc4306: Add dt-bindings for I2C multiplexer/switch i2c: mux: reg: stop double error reporting i2c: mux: pinctrl: stop double error reporting ...
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/Kconfig3
-rw-r--r--drivers/i2c/busses/i2c-designware-baytrail.c8
-rw-r--r--drivers/i2c/busses/i2c-designware-core.c11
-rw-r--r--drivers/i2c/busses/i2c-designware-core.h4
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c56
-rw-r--r--drivers/i2c/busses/i2c-exynos5.c116
-rw-r--r--drivers/i2c/busses/i2c-img-scb.c5
-rw-r--r--drivers/i2c/busses/i2c-meson.c134
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c15
-rw-r--r--drivers/i2c/busses/i2c-rcar.c8
-rw-r--r--drivers/i2c/busses/i2c-scmi.c4
-rw-r--r--drivers/i2c/busses/i2c-tegra-bpmp.c2
-rw-r--r--drivers/i2c/busses/i2c-thunderx-pcidrv.c25
-rw-r--r--drivers/i2c/busses/i2c-xlp9xx.c1
-rw-r--r--drivers/i2c/i2c-core.c62
-rw-r--r--drivers/i2c/i2c-mux.c9
-rw-r--r--drivers/i2c/muxes/Kconfig11
-rw-r--r--drivers/i2c/muxes/Makefile1
-rw-r--r--drivers/i2c/muxes/i2c-arb-gpio-challenge.c4
-rw-r--r--drivers/i2c/muxes/i2c-mux-gpio.c4
-rw-r--r--drivers/i2c/muxes/i2c-mux-ltc4306.c322
-rw-r--r--drivers/i2c/muxes/i2c-mux-pca9541.c4
-rw-r--r--drivers/i2c/muxes/i2c-mux-pca954x.c19
-rw-r--r--drivers/i2c/muxes/i2c-mux-pinctrl.c4
-rw-r--r--drivers/i2c/muxes/i2c-mux-reg.c4
25 files changed, 588 insertions, 248 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 8adc0f1d7ad0..144cbadc7c72 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -933,6 +933,7 @@ config I2C_TEGRA
config I2C_TEGRA_BPMP
tristate "NVIDIA Tegra BPMP I2C controller"
depends on TEGRA_BPMP
+ default y
help
If you say yes to this option, support will be included for the I2C
controller embedded in NVIDIA Tegra SoCs accessed via the BPMP.
@@ -1021,7 +1022,7 @@ config I2C_XLR
config I2C_XLP9XX
tristate "XLP9XX I2C support"
- depends on CPU_XLP || ARCH_VULCAN || COMPILE_TEST
+ depends on CPU_XLP || ARCH_THUNDER2 || COMPILE_TEST
help
This driver enables support for the on-chip I2C interface of
the Broadcom XLP9xx/XLP5xx MIPS and Vulcan ARM64 processors.
diff --git a/drivers/i2c/busses/i2c-designware-baytrail.c b/drivers/i2c/busses/i2c-designware-baytrail.c
index 1749a0f5a9fa..dbda8c9c8a1c 100644
--- a/drivers/i2c/busses/i2c-designware-baytrail.c
+++ b/drivers/i2c/busses/i2c-designware-baytrail.c
@@ -22,7 +22,7 @@
#include "i2c-designware-core.h"
-#define SEMAPHORE_TIMEOUT 100
+#define SEMAPHORE_TIMEOUT 500
#define PUNIT_SEMAPHORE 0x7
#define PUNIT_SEMAPHORE_CHT 0x10e
#define PUNIT_SEMAPHORE_BIT BIT(0)
@@ -70,7 +70,7 @@ static void reset_semaphore(struct dw_i2c_dev *dev)
static int baytrail_i2c_acquire(struct dw_i2c_dev *dev)
{
- u32 addr = get_sem_addr(dev);
+ u32 addr;
u32 sem = PUNIT_SEMAPHORE_ACQUIRE;
int ret;
unsigned long start, end;
@@ -94,6 +94,8 @@ static int baytrail_i2c_acquire(struct dw_i2c_dev *dev)
*/
pm_qos_update_request(&dev->pm_qos, 0);
+ addr = get_sem_addr(dev);
+
/* host driver writes to side band semaphore register */
ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, addr, sem);
if (ret) {
@@ -170,7 +172,7 @@ int i2c_dw_probe_lock_support(struct dw_i2c_dev *dev)
dev_info(dev->dev, "I2C bus managed by PUNIT\n");
dev->acquire_lock = baytrail_i2c_acquire;
dev->release_lock = baytrail_i2c_release;
- dev->pm_runtime_disabled = true;
+ dev->pm_disabled = true;
pm_qos_add_request(&dev->pm_qos, PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index 15a534818d4f..c453717b753b 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -960,6 +960,7 @@ EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param);
int i2c_dw_probe(struct dw_i2c_dev *dev)
{
struct i2c_adapter *adap = &dev->adapter;
+ unsigned long irq_flags;
int r;
init_completion(&dev->cmd_complete);
@@ -975,9 +976,15 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
adap->dev.parent = dev->dev;
i2c_set_adapdata(adap, dev);
+ if (dev->pm_disabled) {
+ dev_pm_syscore_device(dev->dev, true);
+ irq_flags = IRQF_NO_SUSPEND;
+ } else {
+ irq_flags = IRQF_SHARED | IRQF_COND_SUSPEND;
+ }
+
i2c_dw_disable_int(dev);
- r = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr,
- IRQF_SHARED | IRQF_COND_SUSPEND,
+ r = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr, irq_flags,
dev_name(dev->dev), dev);
if (r) {
dev_err(dev->dev, "failure requesting irq %i: %d\n",
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index 846ea57f85af..a7cf429daf60 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -79,7 +79,7 @@
* @pm_qos: pm_qos_request used while holding a hardware lock on the bus
* @acquire_lock: function to acquire a hardware lock on the bus
* @release_lock: function to release a hardware lock on the bus
- * @pm_runtime_disabled: true if pm runtime is disabled
+ * @pm_disabled: true if power-management should be disabled for this i2c-bus
*
* HCNT and LCNT parameters can be used if the platform knows more accurate
* values than the one computed based only on the input clock frequency.
@@ -128,7 +128,7 @@ struct dw_i2c_dev {
struct pm_qos_request pm_qos;
int (*acquire_lock)(struct dw_i2c_dev *dev);
void (*release_lock)(struct dw_i2c_dev *dev);
- bool pm_runtime_disabled;
+ bool pm_disabled;
};
#define ACCESS_SWAP 0x00000001
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index d8665098dce9..5a4eb6b6bd92 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -85,8 +85,7 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
*hcnt = (u16)objs[0].integer.value;
*lcnt = (u16)objs[1].integer.value;
- if (sda_hold)
- *sda_hold = (u32)objs[2].integer.value;
+ *sda_hold = (u32)objs[2].integer.value;
}
kfree(buf.pointer);
@@ -95,26 +94,55 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
static int dw_i2c_acpi_configure(struct platform_device *pdev)
{
struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+ acpi_handle handle = ACPI_HANDLE(&pdev->dev);
const struct acpi_device_id *id;
+ struct acpi_device *adev;
+ const char *uid;
dev->adapter.nr = -1;
dev->tx_fifo_depth = 32;
dev->rx_fifo_depth = 32;
/*
- * Try to get SDA hold time and *CNT values from an ACPI method if
- * it exists for both supported speed modes.
+ * Try to get SDA hold time and *CNT values from an ACPI method for
+ * selected speed modes.
*/
- dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, NULL);
- dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
- &dev->sda_hold_time);
- dw_i2c_acpi_params(pdev, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt, NULL);
- dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, NULL);
+ switch (dev->clk_freq) {
+ case 100000:
+ dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt,
+ &dev->sda_hold_time);
+ break;
+ case 1000000:
+ dw_i2c_acpi_params(pdev, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt,
+ &dev->sda_hold_time);
+ break;
+ case 3400000:
+ dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt,
+ &dev->sda_hold_time);
+ break;
+ case 400000:
+ default:
+ dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
+ &dev->sda_hold_time);
+ break;
+ }
id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
if (id && id->driver_data)
dev->flags |= (u32)id->driver_data;
+ if (acpi_bus_get_device(handle, &adev))
+ return -ENODEV;
+
+ /*
+ * Cherrytrail I2C7 gets used for the PMIC which gets accessed
+ * through ACPI opregions during late suspend / early resume
+ * disable pm for it.
+ */
+ uid = adev->pnp.unique_id;
+ if ((dev->flags & MODEL_CHERRYTRAIL) && !strcmp(uid, "7"))
+ dev->pm_disabled = true;
+
return 0;
}
@@ -286,7 +314,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev));
adap->dev.of_node = pdev->dev.of_node;
- if (dev->pm_runtime_disabled) {
+ if (dev->pm_disabled) {
pm_runtime_forbid(&pdev->dev);
} else {
pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
@@ -302,7 +330,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
return r;
exit_probe:
- if (!dev->pm_runtime_disabled)
+ if (!dev->pm_disabled)
pm_runtime_disable(&pdev->dev);
exit_reset:
if (!IS_ERR_OR_NULL(dev->rst))
@@ -322,7 +350,7 @@ static int dw_i2c_plat_remove(struct platform_device *pdev)
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
- if (!dev->pm_runtime_disabled)
+ if (!dev->pm_disabled)
pm_runtime_disable(&pdev->dev);
if (!IS_ERR_OR_NULL(dev->rst))
reset_control_assert(dev->rst);
@@ -374,9 +402,7 @@ static int dw_i2c_plat_resume(struct device *dev)
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
i2c_dw_plat_prepare_clk(i_dev, true);
-
- if (!i_dev->pm_runtime_disabled)
- i2c_dw_init(i_dev);
+ i2c_dw_init(i_dev);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c
index 736a82472101..23ed4d67ecad 100644
--- a/drivers/i2c/busses/i2c-exynos5.c
+++ b/drivers/i2c/busses/i2c-exynos5.c
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/of_address.h>
+#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/spinlock.h>
@@ -168,8 +169,6 @@
*/
#define HSI2C_HS_TX_CLOCK 1000000
#define HSI2C_FS_TX_CLOCK 100000
-#define HSI2C_HIGH_SPD 1
-#define HSI2C_FAST_SPD 0
#define EXYNOS5_I2C_TIMEOUT (msecs_to_jiffies(1000))
@@ -200,18 +199,10 @@ struct exynos5_i2c {
int trans_done;
/* Controller operating frequency */
- unsigned int fs_clock;
- unsigned int hs_clock;
-
- /*
- * HSI2C Controller can operate in
- * 1. High speed upto 3.4Mbps
- * 2. Fast speed upto 1Mbps
- */
- int speed_mode;
+ unsigned int op_clock;
/* Version of HS-I2C Hardware */
- struct exynos_hsi2c_variant *variant;
+ const struct exynos_hsi2c_variant *variant;
};
/**
@@ -257,15 +248,6 @@ static const struct of_device_id exynos5_i2c_match[] = {
};
MODULE_DEVICE_TABLE(of, exynos5_i2c_match);
-static inline struct exynos_hsi2c_variant *exynos5_i2c_get_variant
- (struct platform_device *pdev)
-{
- const struct of_device_id *match;
-
- match = of_match_node(exynos5_i2c_match, pdev->dev.of_node);
- return (struct exynos_hsi2c_variant *)match->data;
-}
-
static void exynos5_i2c_clr_pend_irq(struct exynos5_i2c *i2c)
{
writel(readl(i2c->regs + HSI2C_INT_STATUS),
@@ -279,7 +261,7 @@ static void exynos5_i2c_clr_pend_irq(struct exynos5_i2c *i2c)
* Returns 0 on success, -EINVAL if the cycle length cannot
* be calculated.
*/
-static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, int mode)
+static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
{
u32 i2c_timing_s1;
u32 i2c_timing_s2;
@@ -292,9 +274,10 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, int mode)
unsigned int t_sr_release;
unsigned int t_ftl_cycle;
unsigned int clkin = clk_get_rate(i2c->clk);
- unsigned int div, utemp0 = 0, utemp1 = 0, clk_cycle;
- unsigned int op_clk = (mode == HSI2C_HIGH_SPD) ?
- i2c->hs_clock : i2c->fs_clock;
+ unsigned int op_clk = hs_timings ? i2c->op_clock :
+ (i2c->op_clock >= HSI2C_HS_TX_CLOCK) ? HSI2C_FS_TX_CLOCK :
+ i2c->op_clock;
+ int div, clk_cycle, temp;
/*
* In case of HSI2C controller in Exynos5 series
@@ -305,33 +288,22 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, int mode)
* FPCLK / FI2C =
* (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2) + 8 + FLT_CYCLE
*
- * utemp0 = (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2)
- * utemp1 = (TSCLK_L + TSCLK_H + 2)
+ * clk_cycle := TSCLK_L + TSCLK_H
+ * temp := (CLK_DIV + 1) * (clk_cycle + 2)
+ *
+ * Constraints: 4 <= temp, 0 <= CLK_DIV < 256, 2 <= clk_cycle <= 510
+ *
*/
t_ftl_cycle = (readl(i2c->regs + HSI2C_CONF) >> 16) & 0x7;
- utemp0 = (clkin / op_clk) - 8;
-
- if (i2c->variant->hw == HSI2C_EXYNOS7)
- utemp0 -= t_ftl_cycle;
- else
- utemp0 -= 2 * t_ftl_cycle;
-
- /* CLK_DIV max is 256 */
- for (div = 0; div < 256; div++) {
- utemp1 = utemp0 / (div + 1);
-
- /*
- * SCL_L and SCL_H each has max value of 255
- * Hence, For the clk_cycle to the have right value
- * utemp1 has to be less then 512 and more than 4.
- */
- if ((utemp1 < 512) && (utemp1 > 4)) {
- clk_cycle = utemp1 - 2;
- break;
- } else if (div == 255) {
- dev_warn(i2c->dev, "Failed to calculate divisor");
- return -EINVAL;
- }
+ temp = clkin / op_clk - 8 - t_ftl_cycle;
+ if (i2c->variant->hw != HSI2C_EXYNOS7)
+ temp -= t_ftl_cycle;
+ div = temp / 512;
+ clk_cycle = temp / (div + 1) - 2;
+ if (temp < 4 || div >= 256 || clk_cycle < 2) {
+ dev_err(i2c->dev, "%s clock set-up failed\n",
+ hs_timings ? "HS" : "FS");
+ return -EINVAL;
}
t_scl_l = clk_cycle / 2;
@@ -356,7 +328,7 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, int mode)
div, t_sr_release);
dev_dbg(i2c->dev, "tDATA_HD: %X\n", t_data_hd);
- if (mode == HSI2C_HIGH_SPD) {
+ if (hs_timings) {
writel(i2c_timing_s1, i2c->regs + HSI2C_TIMING_HS1);
writel(i2c_timing_s2, i2c->regs + HSI2C_TIMING_HS2);
writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_HS3);
@@ -372,24 +344,13 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, int mode)
static int exynos5_hsi2c_clock_setup(struct exynos5_i2c *i2c)
{
- /*
- * Configure the Fast speed timing values
- * Even the High Speed mode initially starts with Fast mode
- */
- if (exynos5_i2c_set_timing(i2c, HSI2C_FAST_SPD)) {
- dev_err(i2c->dev, "HSI2C FS Clock set up failed\n");
- return -EINVAL;
- }
+ /* always set Fast Speed timings */
+ int ret = exynos5_i2c_set_timing(i2c, false);
- /* configure the High speed timing values */
- if (i2c->speed_mode == HSI2C_HIGH_SPD) {
- if (exynos5_i2c_set_timing(i2c, HSI2C_HIGH_SPD)) {
- dev_err(i2c->dev, "HSI2C HS Clock set up failed\n");
- return -EINVAL;
- }
- }
+ if (ret < 0 || i2c->op_clock < HSI2C_HS_TX_CLOCK)
+ return ret;
- return 0;
+ return exynos5_i2c_set_timing(i2c, true);
}
/*
@@ -409,7 +370,7 @@ static void exynos5_i2c_init(struct exynos5_i2c *i2c)
i2c->regs + HSI2C_CTL);
writel(HSI2C_TRAILING_COUNT, i2c->regs + HSI2C_TRAILIG_CTL);
- if (i2c->speed_mode == HSI2C_HIGH_SPD) {
+ if (i2c->op_clock >= HSI2C_HS_TX_CLOCK) {
writel(HSI2C_MASTER_ID(MASTER_ID(i2c->adap.nr)),
i2c->regs + HSI2C_ADDR);
i2c_conf |= HSI2C_HS_MODE;
@@ -747,26 +708,14 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct exynos5_i2c *i2c;
struct resource *mem;
- unsigned int op_clock;
int ret;
i2c = devm_kzalloc(&pdev->dev, sizeof(struct exynos5_i2c), GFP_KERNEL);
if (!i2c)
return -ENOMEM;
- if (of_property_read_u32(np, "clock-frequency", &op_clock)) {
- i2c->speed_mode = HSI2C_FAST_SPD;
- i2c->fs_clock = HSI2C_FS_TX_CLOCK;
- } else {
- if (op_clock >= HSI2C_HS_TX_CLOCK) {
- i2c->speed_mode = HSI2C_HIGH_SPD;
- i2c->fs_clock = HSI2C_FS_TX_CLOCK;
- i2c->hs_clock = op_clock;
- } else {
- i2c->speed_mode = HSI2C_FAST_SPD;
- i2c->fs_clock = op_clock;
- }
- }
+ if (of_property_read_u32(np, "clock-frequency", &i2c->op_clock))
+ i2c->op_clock = HSI2C_FS_TX_CLOCK;
strlcpy(i2c->adap.name, "exynos5-i2c", sizeof(i2c->adap.name));
i2c->adap.owner = THIS_MODULE;
@@ -817,8 +766,7 @@ static int exynos5_i2c_probe(struct platform_device *pdev)
goto err_clk;
}
- /* Need to check the variant before setting up. */
- i2c->variant = exynos5_i2c_get_variant(pdev);
+ i2c->variant = of_device_get_match_data(&pdev->dev);
ret = exynos5_hsi2c_clock_setup(i2c);
if (ret)
diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c
index db8e8b40569d..84fb35f6837f 100644
--- a/drivers/i2c/busses/i2c-img-scb.c
+++ b/drivers/i2c/busses/i2c-img-scb.c
@@ -1362,9 +1362,8 @@ static int img_i2c_probe(struct platform_device *pdev)
}
/* Set up the exception check timer */
- init_timer(&i2c->check_timer);
- i2c->check_timer.function = img_i2c_check_timer;
- i2c->check_timer.data = (unsigned long)i2c;
+ setup_timer(&i2c->check_timer, img_i2c_check_timer,
+ (unsigned long)i2c);
i2c->bitrate = timings[0].max_bitrate;
if (!of_property_read_u32(node, "clock-frequency", &val))
diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
index 73b97c71a484..88d15b92ec35 100644
--- a/drivers/i2c/busses/i2c-meson.c
+++ b/drivers/i2c/busses/i2c-meson.c
@@ -35,10 +35,11 @@
#define REG_CTRL_STATUS BIT(2)
#define REG_CTRL_ERROR BIT(3)
#define REG_CTRL_CLKDIV_SHIFT 12
-#define REG_CTRL_CLKDIV_MASK ((BIT(10) - 1) << REG_CTRL_CLKDIV_SHIFT)
+#define REG_CTRL_CLKDIV_MASK GENMASK(21, 12)
+#define REG_CTRL_CLKDIVEXT_SHIFT 28
+#define REG_CTRL_CLKDIVEXT_MASK GENMASK(29, 28)
#define I2C_TIMEOUT_MS 500
-#define DEFAULT_FREQ 100000
enum {
TOKEN_END = 0,
@@ -54,7 +55,6 @@ enum {
STATE_IDLE,
STATE_READ,
STATE_WRITE,
- STATE_STOP,
};
/**
@@ -73,7 +73,6 @@ enum {
* @error: Flag set when an error is received
* @lock: To avoid race conditions between irq handler and xfer code
* @done: Completion used to wait for transfer termination
- * @frequency: Operating frequency of I2C bus clock
* @tokens: Sequence of tokens to be written to the device
* @num_tokens: Number of tokens
*/
@@ -82,7 +81,6 @@ struct meson_i2c {
struct device *dev;
void __iomem *regs;
struct clk *clk;
- int irq;
struct i2c_msg *msg;
int state;
@@ -93,7 +91,6 @@ struct meson_i2c {
spinlock_t lock;
struct completion done;
- unsigned int frequency;
u32 tokens[2];
int num_tokens;
};
@@ -126,23 +123,27 @@ static void meson_i2c_add_token(struct meson_i2c *i2c, int token)
i2c->num_tokens++;
}
-static void meson_i2c_write_tokens(struct meson_i2c *i2c)
-{
- writel(i2c->tokens[0], i2c->regs + REG_TOK_LIST0);
- writel(i2c->tokens[1], i2c->regs + REG_TOK_LIST1);
-}
-
-static void meson_i2c_set_clk_div(struct meson_i2c *i2c)
+static void meson_i2c_set_clk_div(struct meson_i2c *i2c, unsigned int freq)
{
unsigned long clk_rate = clk_get_rate(i2c->clk);
unsigned int div;
- div = DIV_ROUND_UP(clk_rate, i2c->frequency * 4);
+ div = DIV_ROUND_UP(clk_rate, freq * 4);
+
+ /* clock divider has 12 bits */
+ if (div >= (1 << 12)) {
+ dev_err(i2c->dev, "requested bus frequency too low\n");
+ div = (1 << 12) - 1;
+ }
+
meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIV_MASK,
- div << REG_CTRL_CLKDIV_SHIFT);
+ (div & GENMASK(9, 0)) << REG_CTRL_CLKDIV_SHIFT);
+
+ meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIVEXT_MASK,
+ (div >> 10) << REG_CTRL_CLKDIVEXT_SHIFT);
dev_dbg(i2c->dev, "%s: clk %lu, freq %u, div %u\n", __func__,
- clk_rate, i2c->frequency, div);
+ clk_rate, freq, div);
}
static void meson_i2c_get_data(struct meson_i2c *i2c, char *buf, int len)
@@ -156,10 +157,10 @@ static void meson_i2c_get_data(struct meson_i2c *i2c, char *buf, int len)
dev_dbg(i2c->dev, "%s: data %08x %08x len %d\n", __func__,
rdata0, rdata1, len);
- for (i = 0; i < min_t(int, 4, len); i++)
+ for (i = 0; i < min(4, len); i++)
*buf++ = (rdata0 >> i * 8) & 0xff;
- for (i = 4; i < min_t(int, 8, len); i++)
+ for (i = 4; i < min(8, len); i++)
*buf++ = (rdata1 >> (i - 4) * 8) & 0xff;
}
@@ -168,10 +169,10 @@ static void meson_i2c_put_data(struct meson_i2c *i2c, char *buf, int len)
u32 wdata0 = 0, wdata1 = 0;
int i;
- for (i = 0; i < min_t(int, 4, len); i++)
+ for (i = 0; i < min(4, len); i++)
wdata0 |= *buf++ << (i * 8);
- for (i = 4; i < min_t(int, 8, len); i++)
+ for (i = 4; i < min(8, len); i++)
wdata1 |= *buf++ << ((i - 4) * 8);
writel(wdata0, i2c->regs + REG_TOK_WDATA0);
@@ -186,7 +187,7 @@ static void meson_i2c_prepare_xfer(struct meson_i2c *i2c)
bool write = !(i2c->msg->flags & I2C_M_RD);
int i;
- i2c->count = min_t(int, i2c->msg->len - i2c->pos, 8);
+ i2c->count = min(i2c->msg->len - i2c->pos, 8);
for (i = 0; i < i2c->count - 1; i++)
meson_i2c_add_token(i2c, TOKEN_DATA);
@@ -200,19 +201,12 @@ static void meson_i2c_prepare_xfer(struct meson_i2c *i2c)
if (write)
meson_i2c_put_data(i2c, i2c->msg->buf + i2c->pos, i2c->count);
-}
-
-static void meson_i2c_stop(struct meson_i2c *i2c)
-{
- dev_dbg(i2c->dev, "%s: last %d\n", __func__, i2c->last);
- if (i2c->last) {
- i2c->state = STATE_STOP;
+ if (i2c->last && i2c->pos + i2c->count >= i2c->msg->len)
meson_i2c_add_token(i2c, TOKEN_STOP);
- } else {
- i2c->state = STATE_IDLE;
- complete(&i2c->done);
- }
+
+ writel(i2c->tokens[0], i2c->regs + REG_TOK_LIST0);
+ writel(i2c->tokens[1], i2c->regs + REG_TOK_LIST1);
}
static irqreturn_t meson_i2c_irq(int irqno, void *dev_id)
@@ -223,12 +217,18 @@ static irqreturn_t meson_i2c_irq(int irqno, void *dev_id)
spin_lock(&i2c->lock);
meson_i2c_reset_tokens(i2c);
+ meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0);
ctrl = readl(i2c->regs + REG_CTRL);
dev_dbg(i2c->dev, "irq: state %d, pos %d, count %d, ctrl %08x\n",
i2c->state, i2c->pos, i2c->count, ctrl);
- if (ctrl & REG_CTRL_ERROR && i2c->state != STATE_IDLE) {
+ if (i2c->state == STATE_IDLE) {
+ spin_unlock(&i2c->lock);
+ return IRQ_NONE;
+ }
+
+ if (ctrl & REG_CTRL_ERROR) {
/*
* The bit is set when the IGNORE_NAK bit is cleared
* and the device didn't respond. In this case, the
@@ -242,48 +242,21 @@ static irqreturn_t meson_i2c_irq(int irqno, void *dev_id)
goto out;
}
- switch (i2c->state) {
- case STATE_READ:
- if (i2c->count > 0) {
- meson_i2c_get_data(i2c, i2c->msg->buf + i2c->pos,
- i2c->count);
- i2c->pos += i2c->count;
- }
-
- if (i2c->pos >= i2c->msg->len) {
- meson_i2c_stop(i2c);
- break;
- }
-
- meson_i2c_prepare_xfer(i2c);
- break;
- case STATE_WRITE:
- i2c->pos += i2c->count;
+ if (i2c->state == STATE_READ && i2c->count)
+ meson_i2c_get_data(i2c, i2c->msg->buf + i2c->pos, i2c->count);
- if (i2c->pos >= i2c->msg->len) {
- meson_i2c_stop(i2c);
- break;
- }
+ i2c->pos += i2c->count;
- meson_i2c_prepare_xfer(i2c);
- break;
- case STATE_STOP:
+ if (i2c->pos >= i2c->msg->len) {
i2c->state = STATE_IDLE;
complete(&i2c->done);
- break;
- case STATE_IDLE:
- break;
+ goto out;
}
+ /* Restart the processing */
+ meson_i2c_prepare_xfer(i2c);
+ meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, REG_CTRL_START);
out:
- if (i2c->state != STATE_IDLE) {
- /* Restart the processing */
- meson_i2c_write_tokens(i2c);
- meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START, 0);
- meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_START,
- REG_CTRL_START);
- }
-
spin_unlock(&i2c->lock);
return IRQ_HANDLED;
@@ -323,7 +296,6 @@ static int meson_i2c_xfer_msg(struct meson_i2c *i2c, struct i2c_msg *msg,
i2c->state = (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE;
meson_i2c_prepare_xfer(i2c);
- meson_i2c_write_tokens(i2c);
reinit_completion(&i2c->done);
/* Start the transfer */
@@ -359,21 +331,19 @@ static int meson_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num)
{
struct meson_i2c *i2c = adap->algo_data;
- int i, ret = 0, count = 0;
+ int i, ret = 0;
clk_enable(i2c->clk);
- meson_i2c_set_clk_div(i2c);
for (i = 0; i < num; i++) {
ret = meson_i2c_xfer_msg(i2c, msgs + i, i == num - 1);
if (ret)
break;
- count++;
}
clk_disable(i2c->clk);
- return ret ? ret : count;
+ return ret ?: i;
}
static u32 meson_i2c_func(struct i2c_adapter *adap)
@@ -391,15 +361,14 @@ static int meson_i2c_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node;
struct meson_i2c *i2c;
struct resource *mem;
- int ret = 0;
+ struct i2c_timings timings;
+ int irq, ret = 0;
i2c = devm_kzalloc(&pdev->dev, sizeof(struct meson_i2c), GFP_KERNEL);
if (!i2c)
return -ENOMEM;
- if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
- &i2c->frequency))
- i2c->frequency = DEFAULT_FREQ;
+ i2c_parse_fw_timings(&pdev->dev, &timings, true);
i2c->dev = &pdev->dev;
platform_set_drvdata(pdev, i2c);
@@ -418,14 +387,13 @@ static int meson_i2c_probe(struct platform_device *pdev)
if (IS_ERR(i2c->regs))
return PTR_ERR(i2c->regs);
- i2c->irq = platform_get_irq(pdev, 0);
- if (i2c->irq < 0) {
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
dev_err(&pdev->dev, "can't find IRQ\n");
- return i2c->irq;
+ return irq;
}
- ret = devm_request_irq(&pdev->dev, i2c->irq, meson_i2c_irq,
- 0, dev_name(&pdev->dev), i2c);
+ ret = devm_request_irq(&pdev->dev, irq, meson_i2c_irq, 0, NULL, i2c);
if (ret < 0) {
dev_err(&pdev->dev, "can't request IRQ\n");
return ret;
@@ -457,6 +425,8 @@ static int meson_i2c_probe(struct platform_device *pdev)
return ret;
}
+ meson_i2c_set_clk_div(i2c, timings.bus_freq_hz);
+
return 0;
}
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index a50bd6891e27..cf737ec8563b 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -823,13 +823,10 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
drv_data->rstc = devm_reset_control_get_optional(dev, NULL);
if (IS_ERR(drv_data->rstc)) {
- if (PTR_ERR(drv_data->rstc) == -EPROBE_DEFER) {
- rc = -EPROBE_DEFER;
- goto out;
- }
- } else {
- reset_control_deassert(drv_data->rstc);
+ rc = PTR_ERR(drv_data->rstc);
+ goto out;
}
+ reset_control_deassert(drv_data->rstc);
/* Its not yet defined how timeouts will be specified in device tree.
* So hard code the value to 1 second.
@@ -951,8 +948,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
exit_free_irq:
free_irq(drv_data->irq, drv_data);
exit_reset:
- if (!IS_ERR_OR_NULL(drv_data->rstc))
- reset_control_assert(drv_data->rstc);
+ reset_control_assert(drv_data->rstc);
exit_clk:
/* Not all platforms have a clk */
if (!IS_ERR(drv_data->clk))
@@ -968,8 +964,7 @@ mv64xxx_i2c_remove(struct platform_device *dev)
i2c_del_adapter(&drv_data->adapter);
free_irq(drv_data->irq, drv_data);
- if (!IS_ERR_OR_NULL(drv_data->rstc))
- reset_control_assert(drv_data->rstc);
+ reset_control_assert(drv_data->rstc);
/* Not all platforms have a clk */
if (!IS_ERR(drv_data->clk))
clk_disable_unprepare(drv_data->clk);
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index 26f2ff22e97e..214bf2835d1f 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -700,6 +700,8 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
pm_runtime_get_sync(dev);
+ rcar_i2c_init(priv);
+
ret = rcar_i2c_bus_barrier(priv);
if (ret < 0)
goto out;
@@ -751,6 +753,7 @@ static int rcar_reg_slave(struct i2c_client *slave)
if (slave->flags & I2C_CLIENT_TEN)
return -EAFNOSUPPORT;
+ /* Keep device active for slave address detection logic */
pm_runtime_get_sync(rcar_i2c_priv_