linux/drivers/i2c/busses/i2c-designware-platdrv.c

505 lines
13 KiB
C
Raw Normal View History

/*
* Synopsys DesignWare I2C adapter driver.
*
* Based on the TI DAVINCI I2C adapter driver.
*
* Copyright (C) 2006 Texas Instruments.
* Copyright (C) 2007 MontaVista Software Inc.
* Copyright (C) 2009 Provigent Ltd.
*
* ----------------------------------------------------------------------------
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* ----------------------------------------------------------------------------
*
*/
#include <linux/acpi.h>
#include <linux/clk-provider.h>
#include <linux/clk.h>
#include <linux/delay.h>
i2c: designware: Do not use parameters from ACPI on Dell Inspiron 7348 ACPI SSCN/FMCN methods were originally added because then the platform can provide the most accurate HCNT/LCNT values to the driver. However, this seems not to be true for Dell Inspiron 7348 where using these causes the touchpad to fail in boot: i2c_hid i2c-DLL0675:00: failed to retrieve report from device. i2c_designware INT3433:00: i2c_dw_handle_tx_abort: lost arbitration i2c_hid i2c-DLL0675:00: failed to retrieve report from device. i2c_designware INT3433:00: controller timed out The values received from ACPI are (in fast mode): HCNT: 72 LCNT: 160 this translates to following timings (input clock is 100MHz on Broadwell): tHIGH: 720 ns (spec min 600 ns) tLOW: 1600 ns (spec min 1300 ns) Bus period: 2920 ns (assuming 300 ns tf and tr) Bus speed: 342.5 kHz Both tHIGH and tLOW are within the I2C specification. The calculated values when ACPI parameters are not used are (in fast mode): HCNT: 87 LCNT: 159 which translates to: tHIGH: 870 ns (spec min 600 ns) tLOW: 1590 ns (spec min 1300 ns) Bus period 3060 ns (assuming 300 ns tf and tr) Bus speed 326.8 kHz These values are also within the I2C specification. Since both ACPI and calculated values meet the I2C specification timing requirements it is hard to say why the touchpad does not function properly with the ACPI values except that the bus speed is higher in this case (but still well below the max 400kHz). Solve this by adding DMI quirk to the driver that disables using ACPI parameters on this particulare machine. Reported-by: Pavel Roskin <plroskin@gmail.com> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Tested-by: Pavel Roskin <plroskin@gmail.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de> Cc: stable@kernel.org
2015-09-24 09:06:54 +00:00
#include <linux/dmi.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_data/i2c-designware.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/reset.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include "i2c-designware-core.h"
static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
{
return clk_get_rate(dev->clk)/1000;
}
#ifdef CONFIG_ACPI
i2c: designware: Do not use parameters from ACPI on Dell Inspiron 7348 ACPI SSCN/FMCN methods were originally added because then the platform can provide the most accurate HCNT/LCNT values to the driver. However, this seems not to be true for Dell Inspiron 7348 where using these causes the touchpad to fail in boot: i2c_hid i2c-DLL0675:00: failed to retrieve report from device. i2c_designware INT3433:00: i2c_dw_handle_tx_abort: lost arbitration i2c_hid i2c-DLL0675:00: failed to retrieve report from device. i2c_designware INT3433:00: controller timed out The values received from ACPI are (in fast mode): HCNT: 72 LCNT: 160 this translates to following timings (input clock is 100MHz on Broadwell): tHIGH: 720 ns (spec min 600 ns) tLOW: 1600 ns (spec min 1300 ns) Bus period: 2920 ns (assuming 300 ns tf and tr) Bus speed: 342.5 kHz Both tHIGH and tLOW are within the I2C specification. The calculated values when ACPI parameters are not used are (in fast mode): HCNT: 87 LCNT: 159 which translates to: tHIGH: 870 ns (spec min 600 ns) tLOW: 1590 ns (spec min 1300 ns) Bus period 3060 ns (assuming 300 ns tf and tr) Bus speed 326.8 kHz These values are also within the I2C specification. Since both ACPI and calculated values meet the I2C specification timing requirements it is hard to say why the touchpad does not function properly with the ACPI values except that the bus speed is higher in this case (but still well below the max 400kHz). Solve this by adding DMI quirk to the driver that disables using ACPI parameters on this particulare machine. Reported-by: Pavel Roskin <plroskin@gmail.com> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Tested-by: Pavel Roskin <plroskin@gmail.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de> Cc: stable@kernel.org
2015-09-24 09:06:54 +00:00
/*
* The HCNT/LCNT information coming from ACPI should be the most accurate
* for given platform. However, some systems get it wrong. On such systems
* we get better results by calculating those based on the input clock.
*/
static const struct dmi_system_id dw_i2c_no_acpi_params[] = {
{
.ident = "Dell Inspiron 7348",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7348"),
},
},
{ }
};
static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
u16 *hcnt, u16 *lcnt, u32 *sda_hold)
{
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
acpi_handle handle = ACPI_HANDLE(&pdev->dev);
union acpi_object *obj;
i2c: designware: Do not use parameters from ACPI on Dell Inspiron 7348 ACPI SSCN/FMCN methods were originally added because then the platform can provide the most accurate HCNT/LCNT values to the driver. However, this seems not to be true for Dell Inspiron 7348 where using these causes the touchpad to fail in boot: i2c_hid i2c-DLL0675:00: failed to retrieve report from device. i2c_designware INT3433:00: i2c_dw_handle_tx_abort: lost arbitration i2c_hid i2c-DLL0675:00: failed to retrieve report from device. i2c_designware INT3433:00: controller timed out The values received from ACPI are (in fast mode): HCNT: 72 LCNT: 160 this translates to following timings (input clock is 100MHz on Broadwell): tHIGH: 720 ns (spec min 600 ns) tLOW: 1600 ns (spec min 1300 ns) Bus period: 2920 ns (assuming 300 ns tf and tr) Bus speed: 342.5 kHz Both tHIGH and tLOW are within the I2C specification. The calculated values when ACPI parameters are not used are (in fast mode): HCNT: 87 LCNT: 159 which translates to: tHIGH: 870 ns (spec min 600 ns) tLOW: 1590 ns (spec min 1300 ns) Bus period 3060 ns (assuming 300 ns tf and tr) Bus speed 326.8 kHz These values are also within the I2C specification. Since both ACPI and calculated values meet the I2C specification timing requirements it is hard to say why the touchpad does not function properly with the ACPI values except that the bus speed is higher in this case (but still well below the max 400kHz). Solve this by adding DMI quirk to the driver that disables using ACPI parameters on this particulare machine. Reported-by: Pavel Roskin <plroskin@gmail.com> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Tested-by: Pavel Roskin <plroskin@gmail.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de> Cc: stable@kernel.org
2015-09-24 09:06:54 +00:00
if (dmi_check_system(dw_i2c_no_acpi_params))
return;
if (ACPI_FAILURE(acpi_evaluate_object(handle, method, NULL, &buf)))
return;
obj = (union acpi_object *)buf.pointer;
if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 3) {
const union acpi_object *objs = obj->package.elements;
*hcnt = (u16)objs[0].integer.value;
*lcnt = (u16)objs[1].integer.value;
*sda_hold = (u32)objs[2].integer.value;
}
kfree(buf.pointer);
}
static int dw_i2c_acpi_configure(struct platform_device *pdev)
{
struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
u32 ss_ht = 0, fp_ht = 0, hs_ht = 0, fs_ht = 0;
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 for
* selected speed modes.
*/
dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, &ss_ht);
dw_i2c_acpi_params(pdev, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt, &fp_ht);
dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, &hs_ht);
dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, &fs_ht);
switch (dev->clk_freq) {
case 100000:
dev->sda_hold_time = ss_ht;
break;
case 1000000:
dev->sda_hold_time = fp_ht;
break;
case 3400000:
dev->sda_hold_time = hs_ht;
break;
case 400000:
default:
dev->sda_hold_time = fs_ht;
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;
}
static const struct acpi_device_id dw_i2c_acpi_match[] = {
{ "INT33C2", 0 },
{ "INT33C3", 0 },
{ "INT3432", 0 },
{ "INT3433", 0 },
{ "80860F41", 0 },
{ "808622C1", MODEL_CHERRYTRAIL },
{ "AMD0010", ACCESS_INTR_MASK },
{ "AMDI0010", ACCESS_INTR_MASK },
{ "AMDI0510", 0 },
{ "APMC0D0F", 0 },
{ "HISI02A1", 0 },
{ "HISI02A2", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
#else
static inline int dw_i2c_acpi_configure(struct platform_device *pdev)
{
return -ENODEV;
}
#endif
static void i2c_dw_configure_master(struct dw_i2c_dev *dev)
{
dev->functionality = I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY;
dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
DW_IC_CON_RESTART_EN;
dev->mode = DW_IC_MASTER;
switch (dev->clk_freq) {
case 100000:
dev->master_cfg |= DW_IC_CON_SPEED_STD;
break;
case 3400000:
dev->master_cfg |= DW_IC_CON_SPEED_HIGH;
break;
default:
dev->master_cfg |= DW_IC_CON_SPEED_FAST;
}
}
static void i2c_dw_configure_slave(struct dw_i2c_dev *dev)
{
dev->functionality = I2C_FUNC_SLAVE | DW_IC_DEFAULT_FUNCTIONALITY;
dev->slave_cfg = DW_IC_CON_RX_FIFO_FULL_HLD_CTRL |
DW_IC_CON_RESTART_EN | DW_IC_CON_STOP_DET_IFADDRESSED;
dev->mode = DW_IC_SLAVE;
switch (dev->clk_freq) {
case 100000:
dev->slave_cfg |= DW_IC_CON_SPEED_STD;
break;
case 3400000:
dev->slave_cfg |= DW_IC_CON_SPEED_HIGH;
break;
default:
dev->slave_cfg |= DW_IC_CON_SPEED_FAST;
}
}
static int i2c_dw_plat_prepare_clk(struct dw_i2c_dev *i_dev, bool prepare)
{
if (IS_ERR(i_dev->clk))
return PTR_ERR(i_dev->clk);
if (prepare)
return clk_prepare_enable(i_dev->clk);
clk_disable_unprepare(i_dev->clk);
return 0;
}
static void dw_i2c_set_fifo_size(struct dw_i2c_dev *dev, int id)
{
u32 param, tx_fifo_depth, rx_fifo_depth;
/*
* Try to detect the FIFO depth if not set by interface driver,
* the depth could be from 2 to 256 from HW spec.
*/
param = i2c_dw_read_comp_param(dev);
tx_fifo_depth = ((param >> 16) & 0xff) + 1;
rx_fifo_depth = ((param >> 8) & 0xff) + 1;
if (!dev->tx_fifo_depth) {
dev->tx_fifo_depth = tx_fifo_depth;
dev->rx_fifo_depth = rx_fifo_depth;
dev->adapter.nr = id;
} else if (tx_fifo_depth >= 2) {
dev->tx_fifo_depth = min_t(u32, dev->tx_fifo_depth,
tx_fifo_depth);
dev->rx_fifo_depth = min_t(u32, dev->rx_fifo_depth,
rx_fifo_depth);
}
}
static int dw_i2c_plat_probe(struct platform_device *pdev)
{
struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct i2c_adapter *adap;
struct dw_i2c_dev *dev;
u32 acpi_speed, ht = 0;
struct resource *mem;
int irq, ret;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
dev = devm_kzalloc(&pdev->dev, sizeof(struct dw_i2c_dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dev->base = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(dev->base))
return PTR_ERR(dev->base);
dev->dev = &pdev->dev;
dev->irq = irq;
platform_set_drvdata(pdev, dev);
dev->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
if (IS_ERR(dev->rst)) {
if (PTR_ERR(dev->rst) == -EPROBE_DEFER)
return -EPROBE_DEFER;
} else {
reset_control_deassert(dev->rst);
}
if (pdata) {
dev->clk_freq = pdata->i2c_scl_freq;
} else {
device_property_read_u32(&pdev->dev, "i2c-sda-hold-time-ns",
&ht);
device_property_read_u32(&pdev->dev, "i2c-sda-falling-time-ns",
&dev->sda_falling_time);
device_property_read_u32(&pdev->dev, "i2c-scl-falling-time-ns",
&dev->scl_falling_time);
device_property_read_u32(&pdev->dev, "clock-frequency",
&dev->clk_freq);
}
acpi_speed = i2c_acpi_find_bus_speed(&pdev->dev);
/* Some broken DSTDs use 1MiHz instead of 1MHz */
if (acpi_speed == 1048576)
acpi_speed = 1000000;
/*
* Find bus speed from the "clock-frequency" device property, ACPI
* or by using fast mode if neither is set.
*/
if (acpi_speed && dev->clk_freq)
dev->clk_freq = min(dev->clk_freq, acpi_speed);
else if (acpi_speed || dev->clk_freq)
dev->clk_freq = max(dev->clk_freq, acpi_speed);
else
dev->clk_freq = 400000;
if (has_acpi_companion(&pdev->dev))
dw_i2c_acpi_configure(pdev);
/*
* Only standard mode at 100kHz, fast mode at 400kHz,
* fast mode plus at 1MHz and high speed mode at 3.4MHz are supported.
*/
if (dev->clk_freq != 100000 && dev->clk_freq != 400000
&& dev->clk_freq != 1000000 && dev->clk_freq != 3400000) {
dev_err(&pdev->dev,
"%d Hz is unsupported, only 100kHz, 400kHz, 1MHz and 3.4MHz are supported\n",
dev->clk_freq);
ret = -EINVAL;
goto exit_reset;
}
ret = i2c_dw_probe_lock_support(dev);
if (ret)
goto exit_reset;
if (i2c_detect_slave_mode(&pdev->dev))
i2c_dw_configure_slave(dev);
else
i2c_dw_configure_master(dev);
dev->clk = devm_clk_get(&pdev->dev, NULL);
if (!i2c_dw_plat_prepare_clk(dev, true)) {
dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
if (!dev->sda_hold_time && ht)
dev->sda_hold_time = div_u64(
(u64)dev->get_clk_rate_khz(dev) * ht + 500000,
1000000);
}
dw_i2c_set_fifo_size(dev, pdev->id);
adap = &dev->adapter;
adap->owner = THIS_MODULE;
adap->class = I2C_CLASS_DEPRECATED;
ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev));
adap->dev.of_node = pdev->dev.of_node;
i2c: designware: Never suspend i2c-busses used for accessing the system PMIC Currently we are already setting a pm_runtime_disabled flag and disabling runtime-pm for i2c-busses used for accessing the system PMIC on x86. But this is not enough, there are ACPI opregions which may want to access the PMIC during late-suspend and early-resume, so we need to completely disable pm to be safe. This commit renames the flag from pm_runtime_disabled to pm_disabled and adds the following new behavior if the flag is set: 1) Call dev_pm_syscore_device(dev, true) which disables normal suspend / resume and remove the pm_runtime_disabled check from dw_i2c_plat_resume since that will now never get called. This fixes suspend_late handlers which use ACPI PMIC opregions causing errors like these: PM: Suspending system (freeze) PM: suspend of devices complete after 1127.751 msecs i2c_designware 808622C1:06: timeout waiting for bus ready ACPI Exception: AE_ERROR, Returned by Handler for [UserDefinedRegion] acpi 80860F14:02: Failed to change power state to D3hot PM: late suspend of devices failed 2) Set IRQF_NO_SUSPEND irq flag. This fixes resume_early handlers which handlers which use ACPI PMIC opregions causing errors like these: PM: resume from suspend-to-idle i2c_designware 808622C1:06: controller timed out ACPI Exception: AE_ERROR, Returned by Handler for [UserDefinedRegion] Signed-off-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
2017-03-13 22:25:09 +00:00
if (dev->pm_disabled) {
pm_runtime_forbid(&pdev->dev);
} else {
pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
}
if (dev->mode == DW_IC_SLAVE)
ret = i2c_dw_probe_slave(dev);
else
ret = i2c_dw_probe(dev);
if (ret)
goto exit_probe;
return ret;
exit_probe:
i2c: designware: Never suspend i2c-busses used for accessing the system PMIC Currently we are already setting a pm_runtime_disabled flag and disabling runtime-pm for i2c-busses used for accessing the system PMIC on x86. But this is not enough, there are ACPI opregions which may want to access the PMIC during late-suspend and early-resume, so we need to completely disable pm to be safe. This commit renames the flag from pm_runtime_disabled to pm_disabled and adds the following new behavior if the flag is set: 1) Call dev_pm_syscore_device(dev, true) which disables normal suspend / resume and remove the pm_runtime_disabled check from dw_i2c_plat_resume since that will now never get called. This fixes suspend_late handlers which use ACPI PMIC opregions causing errors like these: PM: Suspending system (freeze) PM: suspend of devices complete after 1127.751 msecs i2c_designware 808622C1:06: timeout waiting for bus ready ACPI Exception: AE_ERROR, Returned by Handler for [UserDefinedRegion] acpi 80860F14:02: Failed to change power state to D3hot PM: late suspend of devices failed 2) Set IRQF_NO_SUSPEND irq flag. This fixes resume_early handlers which handlers which use ACPI PMIC opregions causing errors like these: PM: resume from suspend-to-idle i2c_designware 808622C1:06: controller timed out ACPI Exception: AE_ERROR, Returned by Handler for [UserDefinedRegion] Signed-off-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
2017-03-13 22:25:09 +00:00
if (!dev->pm_disabled)
pm_runtime_disable(&pdev->dev);
exit_reset:
if (!IS_ERR_OR_NULL(dev->rst))
reset_control_assert(dev->rst);
return ret;
}
static int dw_i2c_plat_remove(struct platform_device *pdev)
{
struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
pm_runtime_get_sync(&pdev->dev);
i2c_del_adapter(&dev->adapter);
dev->disable(dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_sync(&pdev->dev);
i2c: designware: Never suspend i2c-busses used for accessing the system PMIC Currently we are already setting a pm_runtime_disabled flag and disabling runtime-pm for i2c-busses used for accessing the system PMIC on x86. But this is not enough, there are ACPI opregions which may want to access the PMIC during late-suspend and early-resume, so we need to completely disable pm to be safe. This commit renames the flag from pm_runtime_disabled to pm_disabled and adds the following new behavior if the flag is set: 1) Call dev_pm_syscore_device(dev, true) which disables normal suspend / resume and remove the pm_runtime_disabled check from dw_i2c_plat_resume since that will now never get called. This fixes suspend_late handlers which use ACPI PMIC opregions causing errors like these: PM: Suspending system (freeze) PM: suspend of devices complete after 1127.751 msecs i2c_designware 808622C1:06: timeout waiting for bus ready ACPI Exception: AE_ERROR, Returned by Handler for [UserDefinedRegion] acpi 80860F14:02: Failed to change power state to D3hot PM: late suspend of devices failed 2) Set IRQF_NO_SUSPEND irq flag. This fixes resume_early handlers which handlers which use ACPI PMIC opregions causing errors like these: PM: resume from suspend-to-idle i2c_designware 808622C1:06: controller timed out ACPI Exception: AE_ERROR, Returned by Handler for [UserDefinedRegion] Signed-off-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
2017-03-13 22:25:09 +00:00
if (!dev->pm_disabled)
pm_runtime_disable(&pdev->dev);
if (!IS_ERR_OR_NULL(dev->rst))
reset_control_assert(dev->rst);
i2c_dw_remove_lock_support(dev);
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id dw_i2c_of_match[] = {
{ .compatible = "snps,designware-i2c", },
{},
};
MODULE_DEVICE_TABLE(of, dw_i2c_of_match);
#endif
#ifdef CONFIG_PM_SLEEP
static int dw_i2c_plat_prepare(struct device *dev)
{
return pm_runtime_suspended(dev);
}
static void dw_i2c_plat_complete(struct device *dev)
{
if (dev->power.direct_complete)
pm_request_resume(dev);
}
#else
#define dw_i2c_plat_prepare NULL
#define dw_i2c_plat_complete NULL
#endif
#ifdef CONFIG_PM
i2c: designware: Fix system suspend The commit 8503ff166504 ("i2c: designware: Avoid unnecessary resuming during system suspend"), may suggest to the PM core to try out the so called direct_complete path for system sleep. In this path, the PM core treats a runtime suspended device as it's already in a proper low power state for system sleep, which makes it skip calling the system sleep callbacks for the device, except for the ->prepare() and the ->complete() callbacks. However, the PM core may unset the direct_complete flag for a parent device, in case its child device are being system suspended before. In this scenario, the PM core invokes the system sleep callbacks, no matter if the device is runtime suspended or not. Particularly in cases of an existing i2c slave device, the above path is triggered, which breaks the assumption that the i2c device is always runtime resumed whenever the dw_i2c_plat_suspend() is being called. More precisely, dw_i2c_plat_suspend() calls clk_core_disable() and clk_core_unprepare(), for an already disabled/unprepared clock, leading to a splat in the log about clocks calls being wrongly balanced and breaking system sleep. To still allow the direct_complete path in cases when it's possible, but also to keep the fix simple, let's runtime resume the i2c device in the ->suspend() callback, before continuing to put the device into low power state. Note, in cases when the i2c device is attached to the ACPI PM domain, this problem doesn't occur, because ACPI's ->suspend() callback, assigned to acpi_subsys_suspend(), already calls pm_runtime_resume() for the device. It should also be noted that this change does not fix commit 8503ff166504 ("i2c: designware: Avoid unnecessary resuming during system suspend"). Because for the non-ACPI case, the system sleep support was already broken prior that point. Cc: <stable@vger.kernel.org> # v4.4+ Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Tested-by: John Stultz <john.stultz@linaro.org> Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
2017-08-09 13:28:22 +00:00
static int dw_i2c_plat_runtime_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
i_dev->disable(i_dev);
i2c_dw_plat_prepare_clk(i_dev, false);
return 0;
}
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);
i2c_dw_plat_prepare_clk(i_dev, true);
i_dev->init(i_dev);
return 0;
}
i2c: designware: Fix system suspend The commit 8503ff166504 ("i2c: designware: Avoid unnecessary resuming during system suspend"), may suggest to the PM core to try out the so called direct_complete path for system sleep. In this path, the PM core treats a runtime suspended device as it's already in a proper low power state for system sleep, which makes it skip calling the system sleep callbacks for the device, except for the ->prepare() and the ->complete() callbacks. However, the PM core may unset the direct_complete flag for a parent device, in case its child device are being system suspended before. In this scenario, the PM core invokes the system sleep callbacks, no matter if the device is runtime suspended or not. Particularly in cases of an existing i2c slave device, the above path is triggered, which breaks the assumption that the i2c device is always runtime resumed whenever the dw_i2c_plat_suspend() is being called. More precisely, dw_i2c_plat_suspend() calls clk_core_disable() and clk_core_unprepare(), for an already disabled/unprepared clock, leading to a splat in the log about clocks calls being wrongly balanced and breaking system sleep. To still allow the direct_complete path in cases when it's possible, but also to keep the fix simple, let's runtime resume the i2c device in the ->suspend() callback, before continuing to put the device into low power state. Note, in cases when the i2c device is attached to the ACPI PM domain, this problem doesn't occur, because ACPI's ->suspend() callback, assigned to acpi_subsys_suspend(), already calls pm_runtime_resume() for the device. It should also be noted that this change does not fix commit 8503ff166504 ("i2c: designware: Avoid unnecessary resuming during system suspend"). Because for the non-ACPI case, the system sleep support was already broken prior that point. Cc: <stable@vger.kernel.org> # v4.4+ Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Tested-by: John Stultz <john.stultz@linaro.org> Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
2017-08-09 13:28:22 +00:00
#ifdef CONFIG_PM_SLEEP
static int dw_i2c_plat_suspend(struct device *dev)
{
pm_runtime_resume(dev);
return dw_i2c_plat_runtime_suspend(dev);
}
#endif
static const struct dev_pm_ops dw_i2c_dev_pm_ops = {
.prepare = dw_i2c_plat_prepare,
.complete = dw_i2c_plat_complete,
SET_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)
i2c: designware: Fix system suspend The commit 8503ff166504 ("i2c: designware: Avoid unnecessary resuming during system suspend"), may suggest to the PM core to try out the so called direct_complete path for system sleep. In this path, the PM core treats a runtime suspended device as it's already in a proper low power state for system sleep, which makes it skip calling the system sleep callbacks for the device, except for the ->prepare() and the ->complete() callbacks. However, the PM core may unset the direct_complete flag for a parent device, in case its child device are being system suspended before. In this scenario, the PM core invokes the system sleep callbacks, no matter if the device is runtime suspended or not. Particularly in cases of an existing i2c slave device, the above path is triggered, which breaks the assumption that the i2c device is always runtime resumed whenever the dw_i2c_plat_suspend() is being called. More precisely, dw_i2c_plat_suspend() calls clk_core_disable() and clk_core_unprepare(), for an already disabled/unprepared clock, leading to a splat in the log about clocks calls being wrongly balanced and breaking system sleep. To still allow the direct_complete path in cases when it's possible, but also to keep the fix simple, let's runtime resume the i2c device in the ->suspend() callback, before continuing to put the device into low power state. Note, in cases when the i2c device is attached to the ACPI PM domain, this problem doesn't occur, because ACPI's ->suspend() callback, assigned to acpi_subsys_suspend(), already calls pm_runtime_resume() for the device. It should also be noted that this change does not fix commit 8503ff166504 ("i2c: designware: Avoid unnecessary resuming during system suspend"). Because for the non-ACPI case, the system sleep support was already broken prior that point. Cc: <stable@vger.kernel.org> # v4.4+ Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Tested-by: John Stultz <john.stultz@linaro.org> Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Acked-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
2017-08-09 13:28:22 +00:00
SET_RUNTIME_PM_OPS(dw_i2c_plat_runtime_suspend,
dw_i2c_plat_resume,
NULL)
};
#define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops)
#else
#define DW_I2C_DEV_PMOPS NULL
#endif
/* Work with hotplug and coldplug */
MODULE_ALIAS("platform:i2c_designware");
static struct platform_driver dw_i2c_driver = {
.probe = dw_i2c_plat_probe,
.remove = dw_i2c_plat_remove,
.driver = {
.name = "i2c_designware",
.of_match_table = of_match_ptr(dw_i2c_of_match),
.acpi_match_table = ACPI_PTR(dw_i2c_acpi_match),
.pm = DW_I2C_DEV_PMOPS,
},
};
static int __init dw_i2c_init_driver(void)
{
return platform_driver_register(&dw_i2c_driver);
}
subsys_initcall(dw_i2c_init_driver);
static void __exit dw_i2c_exit_driver(void)
{
platform_driver_unregister(&dw_i2c_driver);
}
module_exit(dw_i2c_exit_driver);
MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
MODULE_LICENSE("GPL");