Commit 0d5b1bd3 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'i2c/for-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c updates from Wolfram Sang:

 -I2C core now reports proper OF style module alias. I'd like to repeat
  the note from the commit msg here (Thanks, Javier!):

      NOTE: This patch may break out-of-tree drivers that were relying
            on this behavior, and only had an I2C device ID table even
            when the device was registered via OF.

            There are no remaining drivers in mainline that do this, but
            out-of-tree drivers have to be fixed and define a proper OF
            device ID table to have module auto-loading working.

 - new driver for the SynQuacer I2C controller

 - major refactoring of the QUP driver

 - the piix4 driver now uses request_muxed_region which should fix a
   long standing resource conflict with the sp5100_tco watchdog

 - a bunch of small core & driver improvements

* 'i2c/for-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (53 commits)
  i2c: add support for Socionext SynQuacer I2C controller
  dt-bindings: i2c: add binding for Socionext SynQuacer I2C
  i2c: Update i2c_trace_msg static key to modern api
  i2c: fix parameter of trace_i2c_result
  i2c: imx: avoid taking clk_prepare mutex in PM callbacks
  i2c: imx: use clk notifier for rate changes
  i2c: make i2c_check_addr_validity() static
  i2c: rcar: fix mask value of prohibited bit
  dt-bindings: i2c: document R8A77965 bindings
  i2c: pca-platform: drop gpio from platform data
  i2c: pca-platform: use device_property_read_u32
  i2c: pca-platform: unconditionally use devm_gpiod_get_optional
  sh: sh7785lcr: add GPIO lookup table for i2c controller reset
  i2c: qup: reorganization of driver code to remove polling for qup v2
  i2c: qup: reorganization of driver code to remove polling for qup v1
  i2c: qup: send NACK for last read sub transfers
  i2c: qup: fix buffer overflow for multiple msg of maximum xfer len
  i2c: qup: change completion timeout according to transfer length
  i2c: qup: use the complete transfer length to choose DMA mode
  i2c: qup: proper error handling for i2c error in BAM mode
  ...
parents 49a695ba 0d676a6c
...@@ -41,12 +41,16 @@ Required properties: ...@@ -41,12 +41,16 @@ Required properties:
"nxp", "nxp",
"ramtron", "ramtron",
"renesas", "renesas",
"rohm",
"st", "st",
Some vendors use different model names for chips which are just Some vendors use different model names for chips which are just
variants of the above. Known such exceptions are listed below: variants of the above. Known such exceptions are listed below:
"nxp,se97b" - the fallback is "atmel,24c02",
"renesas,r1ex24002" - the fallback is "atmel,24c02" "renesas,r1ex24002" - the fallback is "atmel,24c02"
"renesas,r1ex24128" - the fallback is "atmel,24c128"
"rohm,br24t01" - the fallback is "atmel,24c01"
- reg: The I2C address of the EEPROM. - reg: The I2C address of the EEPROM.
......
...@@ -13,7 +13,9 @@ Required properties: ...@@ -13,7 +13,9 @@ Required properties:
"renesas,i2c-r8a7794" if the device is a part of a R8A7794 SoC. "renesas,i2c-r8a7794" if the device is a part of a R8A7794 SoC.
"renesas,i2c-r8a7795" if the device is a part of a R8A7795 SoC. "renesas,i2c-r8a7795" if the device is a part of a R8A7795 SoC.
"renesas,i2c-r8a7796" if the device is a part of a R8A7796 SoC. "renesas,i2c-r8a7796" if the device is a part of a R8A7796 SoC.
"renesas,i2c-r8a77965" if the device is a part of a R8A77965 SoC.
"renesas,i2c-r8a77970" if the device is a part of a R8A77970 SoC. "renesas,i2c-r8a77970" if the device is a part of a R8A77970 SoC.
"renesas,i2c-r8a77995" if the device is a part of a R8A77995 SoC.
"renesas,rcar-gen1-i2c" for a generic R-Car Gen1 compatible device. "renesas,rcar-gen1-i2c" for a generic R-Car Gen1 compatible device.
"renesas,rcar-gen2-i2c" for a generic R-Car Gen2 or RZ/G1 compatible "renesas,rcar-gen2-i2c" for a generic R-Car Gen2 or RZ/G1 compatible
device. device.
......
...@@ -13,6 +13,7 @@ Required properties: ...@@ -13,6 +13,7 @@ Required properties:
- "renesas,iic-r8a7794" (R-Car E2) - "renesas,iic-r8a7794" (R-Car E2)
- "renesas,iic-r8a7795" (R-Car H3) - "renesas,iic-r8a7795" (R-Car H3)
- "renesas,iic-r8a7796" (R-Car M3-W) - "renesas,iic-r8a7796" (R-Car M3-W)
- "renesas,iic-r8a77965" (R-Car M3-N)
- "renesas,iic-sh73a0" (SH-Mobile AG5) - "renesas,iic-sh73a0" (SH-Mobile AG5)
- "renesas,rcar-gen2-iic" (generic R-Car Gen2 or RZ/G1 - "renesas,rcar-gen2-iic" (generic R-Car Gen2 or RZ/G1
compatible device) compatible device)
......
Socionext SynQuacer I2C
Required properties:
- compatible : Must be "socionext,synquacer-i2c"
- reg : Offset and length of the register set for the device
- interrupts : A single interrupt specifier
- #address-cells : Must be <1>;
- #size-cells : Must be <0>;
- clock-names : Must contain "pclk".
- clocks : Must contain an entry for each name in clock-names.
(See the common clock bindings.)
Optional properties:
- clock-frequency : Desired I2C bus clock frequency in Hz. As only Normal and
Fast modes are supported, possible values are 100000 and
400000.
Example :
i2c@51210000 {
compatible = "socionext,synquacer-i2c";
reg = <0x51210000 0x1000>;
interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
clock-names = "pclk";
clocks = <&clk_i2c>;
clock-frequency = <400000>;
};
...@@ -6559,7 +6559,7 @@ F: drivers/i2c/muxes/ ...@@ -6559,7 +6559,7 @@ F: drivers/i2c/muxes/
F: include/linux/i2c-mux.h F: include/linux/i2c-mux.h
I2C MV64XXX MARVELL AND ALLWINNER DRIVER I2C MV64XXX MARVELL AND ALLWINNER DRIVER
M: Gregory CLEMENT <gregory.clement@free-electrons.com> M: Gregory CLEMENT <gregory.clement@bootlin.com>
L: linux-i2c@vger.kernel.org L: linux-i2c@vger.kernel.org
S: Maintained S: Maintained
F: drivers/i2c/busses/i2c-mv64xxx.c F: drivers/i2c/busses/i2c-mv64xxx.c
...@@ -12902,6 +12902,13 @@ F: include/media/soc* ...@@ -12902,6 +12902,13 @@ F: include/media/soc*
F: drivers/media/i2c/soc_camera/ F: drivers/media/i2c/soc_camera/
F: drivers/media/platform/soc_camera/ F: drivers/media/platform/soc_camera/
SOCIONEXT SYNQUACER I2C DRIVER
M: Ard Biesheuvel <ard.biesheuvel@linaro.org>
L: linux-i2c@vger.kernel.org
S: Maintained
F: drivers/i2c/busses/i2c-synquacer.c
F: Documentation/devicetree/bindings/i2c/i2c-synquacer.txt
SOCIONEXT UNIPHIER SOUND DRIVER SOCIONEXT UNIPHIER SOUND DRIVER
M: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com> M: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: alsa-devel@alsa-project.org (moderated for non-subscribers)
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/gpio/machine.h>
#include <mach/sh7785lcr.h> #include <mach/sh7785lcr.h>
#include <cpu/sh7785.h> #include <cpu/sh7785.h>
#include <asm/heartbeat.h> #include <asm/heartbeat.h>
...@@ -243,8 +244,15 @@ static struct resource i2c_resources[] = { ...@@ -243,8 +244,15 @@ static struct resource i2c_resources[] = {
}, },
}; };
static struct gpiod_lookup_table i2c_gpio_table = {
.dev_id = "i2c.0",
.table = {
GPIO_LOOKUP("pfc-sh7757", 0, "reset-gpios", GPIO_ACTIVE_LOW),
{ },
},
};
static struct i2c_pca9564_pf_platform_data i2c_platform_data = { static struct i2c_pca9564_pf_platform_data i2c_platform_data = {
.gpio = 0,
.i2c_clock_speed = I2C_PCA_CON_330kHz, .i2c_clock_speed = I2C_PCA_CON_330kHz,
.timeout = HZ, .timeout = HZ,
}; };
...@@ -283,6 +291,7 @@ static int __init sh7785lcr_devices_setup(void) ...@@ -283,6 +291,7 @@ static int __init sh7785lcr_devices_setup(void)
i2c_device.num_resources = ARRAY_SIZE(i2c_proto_resources); i2c_device.num_resources = ARRAY_SIZE(i2c_proto_resources);
} }
gpiod_add_lookup_table(&i2c_gpio_table);
return platform_add_devices(sh7785lcr_devices, return platform_add_devices(sh7785lcr_devices,
ARRAY_SIZE(sh7785lcr_devices)); ARRAY_SIZE(sh7785lcr_devices));
} }
......
...@@ -979,6 +979,16 @@ config I2C_SUN6I_P2WI ...@@ -979,6 +979,16 @@ config I2C_SUN6I_P2WI
This interface is used to connect to specific PMIC devices (like the This interface is used to connect to specific PMIC devices (like the
AXP221). AXP221).
config I2C_SYNQUACER
tristate "Socionext SynQuacer I2C controller"
depends on ARCH_SYNQUACER || COMPILE_TEST
help
Say Y here to include support for the I2C controller used in some
Fujitsu and Socionext SoCs.
This driver can also be built as a module. If so, the module
will be called i2c-synquacer.
config I2C_TEGRA config I2C_TEGRA
tristate "NVIDIA Tegra internal I2C controller" tristate "NVIDIA Tegra internal I2C controller"
depends on ARCH_TEGRA depends on ARCH_TEGRA
......
...@@ -97,6 +97,7 @@ obj-$(CONFIG_I2C_STM32F4) += i2c-stm32f4.o ...@@ -97,6 +97,7 @@ obj-$(CONFIG_I2C_STM32F4) += i2c-stm32f4.o
obj-$(CONFIG_I2C_STM32F7) += i2c-stm32f7.o obj-$(CONFIG_I2C_STM32F7) += i2c-stm32f7.o
obj-$(CONFIG_I2C_STU300) += i2c-stu300.o obj-$(CONFIG_I2C_STU300) += i2c-stu300.o
obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o
obj-$(CONFIG_I2C_SYNQUACER) += i2c-synquacer.o
obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o
obj-$(CONFIG_I2C_TEGRA_BPMP) += i2c-tegra-bpmp.o obj-$(CONFIG_I2C_TEGRA_BPMP) += i2c-tegra-bpmp.o
obj-$(CONFIG_I2C_UNIPHIER) += i2c-uniphier.o obj-$(CONFIG_I2C_UNIPHIER) += i2c-uniphier.o
......
...@@ -163,7 +163,7 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev) ...@@ -163,7 +163,7 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev)
if (!(dev->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK)) if (!(dev->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK))
dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT; dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT;
dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD); dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD);
} else { } else if (dev->sda_hold_time) {
dev_warn(dev->dev, dev_warn(dev->dev,
"Hardware too old to adjust SDA hold time.\n"); "Hardware too old to adjust SDA hold time.\n");
} }
......
...@@ -128,6 +128,10 @@ ...@@ -128,6 +128,10 @@
#define HSI2C_TIMEOUT_EN (1u << 31) #define HSI2C_TIMEOUT_EN (1u << 31)
#define HSI2C_TIMEOUT_MASK 0xff #define HSI2C_TIMEOUT_MASK 0xff
/* I2C_MANUAL_CMD register bits */
#define HSI2C_CMD_READ_DATA (1u << 4)
#define HSI2C_CMD_SEND_STOP (1u << 2)
/* I2C_TRANS_STATUS register bits */ /* I2C_TRANS_STATUS register bits */
#define HSI2C_MASTER_BUSY (1u << 17) #define HSI2C_MASTER_BUSY (1u << 17)
#define HSI2C_SLAVE_BUSY (1u << 16) #define HSI2C_SLAVE_BUSY (1u << 16)
...@@ -441,12 +445,6 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id) ...@@ -441,12 +445,6 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
i2c->state = -ETIMEDOUT; i2c->state = -ETIMEDOUT;
goto stop; goto stop;
} }
trans_status = readl(i2c->regs + HSI2C_TRANS_STATUS);
if ((trans_status & HSI2C_MASTER_ST_MASK) == HSI2C_MASTER_ST_LOSE) {
i2c->state = -EAGAIN;
goto stop;
}
} else if (int_status & HSI2C_INT_I2C) { } else if (int_status & HSI2C_INT_I2C) {
trans_status = readl(i2c->regs + HSI2C_TRANS_STATUS); trans_status = readl(i2c->regs + HSI2C_TRANS_STATUS);
if (trans_status & HSI2C_NO_DEV_ACK) { if (trans_status & HSI2C_NO_DEV_ACK) {
...@@ -544,6 +542,57 @@ static int exynos5_i2c_wait_bus_idle(struct exynos5_i2c *i2c) ...@@ -544,6 +542,57 @@ static int exynos5_i2c_wait_bus_idle(struct exynos5_i2c *i2c)
return -EBUSY; return -EBUSY;
} }
static void exynos5_i2c_bus_recover(struct exynos5_i2c *i2c)
{
u32 val;
val = readl(i2c->regs + HSI2C_CTL) | HSI2C_RXCHON;
writel(val, i2c->regs + HSI2C_CTL);
val = readl(i2c->regs + HSI2C_CONF) & ~HSI2C_AUTO_MODE;
writel(val, i2c->regs + HSI2C_CONF);
/*
* Specification says master should send nine clock pulses. It can be
* emulated by sending manual read command (nine pulses for read eight
* bits + one pulse for NACK).
*/
writel(HSI2C_CMD_READ_DATA, i2c->regs + HSI2C_MANUAL_CMD);
exynos5_i2c_wait_bus_idle(i2c);
writel(HSI2C_CMD_SEND_STOP, i2c->regs + HSI2C_MANUAL_CMD);
exynos5_i2c_wait_bus_idle(i2c);
val = readl(i2c->regs + HSI2C_CTL) & ~HSI2C_RXCHON;
writel(val, i2c->regs + HSI2C_CTL);
val = readl(i2c->regs + HSI2C_CONF) | HSI2C_AUTO_MODE;
writel(val, i2c->regs + HSI2C_CONF);
}
static void exynos5_i2c_bus_check(struct exynos5_i2c *i2c)
{
unsigned long timeout;
if (i2c->variant->hw != HSI2C_EXYNOS7)
return;
/*
* HSI2C_MASTER_ST_LOSE state in EXYNOS7 variant before transaction
* indicates that bus is stuck (SDA is low). In such case bus recovery
* can be performed.
*/
timeout = jiffies + msecs_to_jiffies(100);
for (;;) {
u32 st = readl(i2c->regs + HSI2C_TRANS_STATUS);
if ((st & HSI2C_MASTER_ST_MASK) != HSI2C_MASTER_ST_LOSE)
return;
if (time_is_before_jiffies(timeout))
return;
exynos5_i2c_bus_recover(i2c);
}
}
/* /*
* exynos5_i2c_message_start: Configures the bus and starts the xfer * exynos5_i2c_message_start: Configures the bus and starts the xfer
* i2c: struct exynos5_i2c pointer for the current bus * i2c: struct exynos5_i2c pointer for the current bus
...@@ -598,6 +647,8 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop) ...@@ -598,6 +647,8 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
writel(fifo_ctl, i2c->regs + HSI2C_FIFO_CTL); writel(fifo_ctl, i2c->regs + HSI2C_FIFO_CTL);
writel(i2c_ctl, i2c->regs + HSI2C_CTL); writel(i2c_ctl, i2c->regs + HSI2C_CTL);
exynos5_i2c_bus_check(i2c);
/* /*
* Enable interrupts before starting the transfer so that we don't * Enable interrupts before starting the transfer so that we don't
* miss any INT_I2C interrupts. * miss any INT_I2C interrupts.
......
...@@ -194,6 +194,7 @@ struct imx_i2c_dma { ...@@ -194,6 +194,7 @@ struct imx_i2c_dma {
struct imx_i2c_struct { struct imx_i2c_struct {
struct i2c_adapter adapter; struct i2c_adapter adapter;
struct clk *clk; struct clk *clk;
struct notifier_block clk_change_nb;
void __iomem *base; void __iomem *base;
wait_queue_head_t queue; wait_queue_head_t queue;
unsigned long i2csr; unsigned long i2csr;
...@@ -467,15 +468,14 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx) ...@@ -467,15 +468,14 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
return 0; return 0;
} }
static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx) static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
unsigned int i2c_clk_rate)
{ {
struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div; struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div;
unsigned int i2c_clk_rate;
unsigned int div; unsigned int div;
int i; int i;
/* Divider value calculation */ /* Divider value calculation */
i2c_clk_rate = clk_get_rate(i2c_imx->clk);
if (i2c_imx->cur_clk == i2c_clk_rate) if (i2c_imx->cur_clk == i2c_clk_rate)
return; return;
...@@ -510,6 +510,20 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx) ...@@ -510,6 +510,20 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx)
#endif #endif
} }
static int i2c_imx_clk_notifier_call(struct notifier_block *nb,
unsigned long action, void *data)
{
struct clk_notifier_data *ndata = data;
struct imx_i2c_struct *i2c_imx = container_of(&ndata->clk,
struct imx_i2c_struct,
clk);
if (action & POST_RATE_CHANGE)
i2c_imx_set_clk(i2c_imx, ndata->new_rate);
return NOTIFY_OK;
}
static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
{ {
unsigned int temp = 0; unsigned int temp = 0;
...@@ -517,8 +531,6 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) ...@@ -517,8 +531,6 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
i2c_imx_set_clk(i2c_imx);
imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR); imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR);
/* Enable I2C controller */ /* Enable I2C controller */
imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR); imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
...@@ -1131,6 +1143,9 @@ static int i2c_imx_probe(struct platform_device *pdev) ...@@ -1131,6 +1143,9 @@ static int i2c_imx_probe(struct platform_device *pdev)
"clock-frequency", &i2c_imx->bitrate); "clock-frequency", &i2c_imx->bitrate);
if (ret < 0 && pdata && pdata->bitrate) if (ret < 0 && pdata && pdata->bitrate)
i2c_imx->bitrate = pdata->bitrate; i2c_imx->bitrate = pdata->bitrate;
i2c_imx->clk_change_nb.notifier_call = i2c_imx_clk_notifier_call;
clk_notifier_register(i2c_imx->clk, &i2c_imx->clk_change_nb);
i2c_imx_set_clk(i2c_imx, clk_get_rate(i2c_imx->clk));
/* Set up chip registers to defaults */ /* Set up chip registers to defaults */
imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN, imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
...@@ -1141,12 +1156,12 @@ static int i2c_imx_probe(struct platform_device *pdev) ...@@ -1141,12 +1156,12 @@ static int i2c_imx_probe(struct platform_device *pdev)
ret = i2c_imx_init_recovery_info(i2c_imx, pdev); ret = i2c_imx_init_recovery_info(i2c_imx, pdev);
/* Give it another chance if pinctrl used is not ready yet */ /* Give it another chance if pinctrl used is not ready yet */
if (ret == -EPROBE_DEFER) if (ret == -EPROBE_DEFER)
goto rpm_disable; goto clk_notifier_unregister;
/* Add I2C adapter */ /* Add I2C adapter */
ret = i2c_add_numbered_adapter(&i2c_imx->adapter); ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
if (ret < 0) if (ret < 0)
goto rpm_disable; goto clk_notifier_unregister;
pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev);
...@@ -1162,6 +1177,8 @@ static int i2c_imx_probe(struct platform_device *pdev) ...@@ -1162,6 +1177,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
return 0; /* Return OK */ return 0; /* Return OK */
clk_notifier_unregister:
clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
rpm_disable: rpm_disable:
pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
...@@ -1195,6 +1212,7 @@ static int i2c_imx_remove(struct platform_device *pdev) ...@@ -1195,6 +1212,7 @@ static int i2c_imx_remove(struct platform_device *pdev)
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR); imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR);
imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR); imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR);
clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
clk_disable_unprepare(i2c_imx->clk); clk_disable_unprepare(i2c_imx->clk);
pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
...@@ -1208,7 +1226,7 @@ static int i2c_imx_runtime_suspend(struct device *dev) ...@@ -1208,7 +1226,7 @@ static int i2c_imx_runtime_suspend(struct device *dev)
{ {
struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev); struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
clk_disable_unprepare(i2c_imx->clk); clk_disable(i2c_imx->clk);
return 0; return 0;
} }
...@@ -1218,7 +1236,7 @@ static int i2c_imx_runtime_resume(struct device *dev) ...@@ -1218,7 +1236,7 @@ static int i2c_imx_runtime_resume(struct device *dev)
struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev); struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
int ret; int ret;
ret = clk_prepare_enable(i2c_imx->clk); ret = clk_enable(i2c_imx->clk);
if (ret) if (ret)
dev_err(dev, "can't enable I2C clock, ret=%d\n", ret); dev_err(dev, "can't enable I2C clock, ret=%d\n", ret);
......
...@@ -845,12 +845,16 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, ...@@ -845,12 +845,16 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
*/ */
if (of_device_is_compatible(np, "marvell,mv78230-i2c")) { if (of_device_is_compatible(np, "marvell,mv78230-i2c")) {
drv_data->offload_enabled = true; drv_data->offload_enabled = true;
drv_data->errata_delay = true; /* The delay is only needed in standard mode (100kHz) */
if (bus_freq <= 100000)
drv_data->errata_delay = true;
} }
if (of_device_is_compatible(np, "marvell,mv78230-a0-i2c")) { if (of_device_is_compatible(np, "marvell,mv78230-a0-i2c")) {
drv_data->offload_enabled = false; drv_data->offload_enabled = false;
drv_data->errata_delay = true; /* The delay is only needed in standard mode (100kHz) */
if (bus_freq <= 100000)
drv_data->errata_delay = true;
} }
if (of_device_is_compatible(np, "allwinner,sun6i-a31-i2c")) if (of_device_is_compatible(np, "allwinner,sun6i-a31-i2c"))
......
...@@ -173,33 +173,19 @@ static int i2c_pca_pf_probe(struct platform_device *pdev) ...@@ -173,33 +173,19 @@ static int i2c_pca_pf_probe(struct platform_device *pdev)
i2c->adap.dev.parent = &pdev->dev; i2c->adap.dev.parent = &pdev->dev;
i2c->adap.dev.of_node = np; i2c->adap.dev.of_node = np;
i2c->gpio = devm_gpiod_get_optional(&pdev->dev, "reset-gpios", GPIOD_OUT_LOW);
if (IS_ERR(i2c->gpio))
return PTR_ERR(i2c->gpio);
i2c->adap.timeout = HZ;
ret = device_property_read_u32(&pdev->dev, "clock-frequency",
&i2c->algo_data.i2c_clock);
if (ret)
i2c->algo_data.i2c_clock = 59000;
if (platform_data) { if (platform_data) {
i2c->adap.timeout = platform_data->timeout; i2c->adap.timeout = platform_data->timeout;
i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed; i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed;
if (gpio_is_valid(platform_data->gpio)) {
ret = devm_gpio_request_one(&pdev->dev,
platform_data->gpio,
GPIOF_ACTIVE_LOW,
i2c->adap.name);
if (ret == 0) {
i2c->gpio = gpio_to_desc(platform_data->gpio);
gpiod_direction_output(i2c->gpio, 0);
} else {
dev_warn(&pdev->dev, "Registering gpio failed!\n");
i2c->gpio = NULL;
}
}
} else if (np) {
i2c->adap.timeout = HZ;
i2c->gpio = devm_gpiod_get_optional(&pdev->dev, "reset-gpios", GPIOD_OUT_LOW);
if (IS_ERR(i2c->gpio))
return PTR_ERR(i2c->gpio);
of_property_read_u32_index(np, "clock-frequency", 0,
&i2c->algo_data.i2c_clock);
} else {
i2c->adap.timeout = HZ;
i2c->algo_data.i2c_clock = 59000;
i2c->gpio = NULL;
} }
i2c->algo_data.data = i2c; i2c->algo_data.data = i2c;
......
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/mutex.h>
/* PIIX4 SMBus address offsets */ /* PIIX4 SMBus address offsets */
...@@ -153,10 +152,7 @@ static const struct dmi_system_id piix4_dmi_ibm[] = { ...@@ -153,10 +152,7 @@ static const struct dmi_system_id piix4_dmi_ibm[] = {
/* /*
* SB800 globals * SB800 globals
* piix4_mutex_sb800 protects piix4_port_sel_sb800 and the pair
* of I/O ports at SB800_PIIX4_SMB_IDX.
*/ */
static DEFINE_MUTEX(piix4_mutex_sb800);
static u8 piix4_port_sel_sb800; static u8 piix4_port_sel_sb800;
static u8 piix4_port_mask_sb800; static u8 piix4_port_mask_sb800;
static u8 piix4_port_shift_sb800; static u8 piix4_port_shift_sb800;
...@@ -298,12 +294,19 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, ...@@ -298,12 +294,19 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
else else
smb_en = (aux) ? 0x28 : 0x2c; smb_en = (aux) ? 0x28 : 0x2c;
mutex_lock(&piix4_mutex_sb800); if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2, "sb800_piix4_smb")) {
dev_err(&PIIX4_dev->dev,
"SMB base address index region 0x%x already in use.\n",
SB800_PIIX4_SMB_IDX);
return -EBUSY;
}
outb_p(smb_en, SB800_PIIX4_SMB_IDX); outb_p(smb_en, SB800_PIIX4_SMB_IDX);
smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1); smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX); outb_p(smb_en + 1, SB800_PIIX4_SMB_IDX);
smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1); smba_en_hi = inb_p(SB800_PIIX4_SMB_IDX + 1);
mutex_unlock(&piix4_mutex_sb800);
release_region(SB800_PIIX4_SMB_IDX, 2);
if (!smb_en) { if (!smb_en) {
smb_en_status = smba_en_lo & 0x10; smb_en_status = smba_en_lo & 0x10;
...@@ -373,7 +376,12 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, ...@@ -373,7 +376,12 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
break; break;
} }
} else { } else {
mutex_lock(&piix4_mutex_sb800); if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2,