Skip to content

Commit

Permalink
Merge branch 'i2c/for-4.17' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/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
  ...
torvalds committed Apr 7, 2018
2 parents 49a695b + 0d676a6 commit 0d5b1bd
Showing 28 changed files with 1,969 additions and 770 deletions.
4 changes: 4 additions & 0 deletions Documentation/devicetree/bindings/eeprom/at24.txt
Original file line number Diff line number Diff line change
@@ -41,12 +41,16 @@ Required properties:
"nxp",
"ramtron",
"renesas",
"rohm",
"st",

Some vendors use different model names for chips which are just
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,r1ex24128" - the fallback is "atmel,24c128"
"rohm,br24t01" - the fallback is "atmel,24c01"

- reg: The I2C address of the EEPROM.

2 changes: 2 additions & 0 deletions Documentation/devicetree/bindings/i2c/i2c-rcar.txt
Original file line number Diff line number Diff line change
@@ -13,7 +13,9 @@ Required properties:
"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-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-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-gen2-i2c" for a generic R-Car Gen2 or RZ/G1 compatible
device.
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ Required properties:
- "renesas,iic-r8a7794" (R-Car E2)
- "renesas,iic-r8a7795" (R-Car H3)
- "renesas,iic-r8a7796" (R-Car M3-W)
- "renesas,iic-r8a77965" (R-Car M3-N)
- "renesas,iic-sh73a0" (SH-Mobile AG5)
- "renesas,rcar-gen2-iic" (generic R-Car Gen2 or RZ/G1
compatible device)
29 changes: 29 additions & 0 deletions Documentation/devicetree/bindings/i2c/i2c-synquacer.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
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>;
};
9 changes: 8 additions & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
@@ -6559,7 +6559,7 @@ F: drivers/i2c/muxes/
F: include/linux/i2c-mux.h

I2C MV64XXX MARVELL AND ALLWINNER DRIVER
M: Gregory CLEMENT <gregory.clement@free-electrons.com>
M: Gregory CLEMENT <gregory.clement@bootlin.com>
L: [email protected]
S: Maintained
F: drivers/i2c/busses/i2c-mv64xxx.c
@@ -12902,6 +12902,13 @@ F: include/media/soc*
F: drivers/media/i2c/soc_camera/
F: drivers/media/platform/soc_camera/

SOCIONEXT SYNQUACER I2C DRIVER
M: Ard Biesheuvel <[email protected]>
L: [email protected]
S: Maintained
F: drivers/i2c/busses/i2c-synquacer.c
F: Documentation/devicetree/bindings/i2c/i2c-synquacer.txt

SOCIONEXT UNIPHIER SOUND DRIVER
M: Katsuhiro Suzuki <[email protected]>
L: [email protected] (moderated for non-subscribers)
11 changes: 10 additions & 1 deletion arch/sh/boards/board-sh7785lcr.c
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/errno.h>
#include <linux/gpio/machine.h>
#include <mach/sh7785lcr.h>
#include <cpu/sh7785.h>
#include <asm/heartbeat.h>
@@ -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 = {
.gpio = 0,
.i2c_clock_speed = I2C_PCA_CON_330kHz,
.timeout = HZ,
};
@@ -283,6 +291,7 @@ static int __init sh7785lcr_devices_setup(void)
i2c_device.num_resources = ARRAY_SIZE(i2c_proto_resources);
}

gpiod_add_lookup_table(&i2c_gpio_table);
return platform_add_devices(sh7785lcr_devices,
ARRAY_SIZE(sh7785lcr_devices));
}
10 changes: 10 additions & 0 deletions drivers/i2c/busses/Kconfig
Original file line number Diff line number Diff line change
@@ -979,6 +979,16 @@ config I2C_SUN6I_P2WI
This interface is used to connect to specific PMIC devices (like the
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
tristate "NVIDIA Tegra internal I2C controller"
depends on ARCH_TEGRA
1 change: 1 addition & 0 deletions drivers/i2c/busses/Makefile
Original file line number Diff line number Diff line change
@@ -97,6 +97,7 @@ obj-$(CONFIG_I2C_STM32F4) += i2c-stm32f4.o
obj-$(CONFIG_I2C_STM32F7) += i2c-stm32f7.o
obj-$(CONFIG_I2C_STU300) += i2c-stu300.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_BPMP) += i2c-tegra-bpmp.o
obj-$(CONFIG_I2C_UNIPHIER) += i2c-uniphier.o
2 changes: 1 addition & 1 deletion drivers/i2c/busses/i2c-designware-master.c
Original file line number Diff line number Diff line change
@@ -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))
dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT;
dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD);
} else {
} else if (dev->sda_hold_time) {
dev_warn(dev->dev,
"Hardware too old to adjust SDA hold time.\n");
}
63 changes: 57 additions & 6 deletions drivers/i2c/busses/i2c-exynos5.c
Original file line number Diff line number Diff line change
@@ -128,6 +128,10 @@
#define HSI2C_TIMEOUT_EN (1u << 31)
#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 */
#define HSI2C_MASTER_BUSY (1u << 17)
#define HSI2C_SLAVE_BUSY (1u << 16)
@@ -441,12 +445,6 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
i2c->state = -ETIMEDOUT;
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) {
trans_status = readl(i2c->regs + HSI2C_TRANS_STATUS);
if (trans_status & HSI2C_NO_DEV_ACK) {
@@ -544,6 +542,57 @@ static int exynos5_i2c_wait_bus_idle(struct exynos5_i2c *i2c)
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
* 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)
writel(fifo_ctl, i2c->regs + HSI2C_FIFO_CTL);
writel(i2c_ctl, i2c->regs + HSI2C_CTL);

exynos5_i2c_bus_check(i2c);

/*
* Enable interrupts before starting the transfer so that we don't
* miss any INT_I2C interrupts.
36 changes: 27 additions & 9 deletions drivers/i2c/busses/i2c-imx.c
Original file line number Diff line number Diff line change
@@ -194,6 +194,7 @@ struct imx_i2c_dma {
struct imx_i2c_struct {
struct i2c_adapter adapter;
struct clk *clk;
struct notifier_block clk_change_nb;
void __iomem *base;
wait_queue_head_t queue;
unsigned long i2csr;
@@ -467,15 +468,14 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
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;
unsigned int i2c_clk_rate;
unsigned int div;
int i;

/* Divider value calculation */
i2c_clk_rate = clk_get_rate(i2c_imx->clk);
if (i2c_imx->cur_clk == i2c_clk_rate)
return;

@@ -510,15 +510,27 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx)
#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)
{
unsigned int temp = 0;
int result;

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);
/* Enable I2C controller */
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)
"clock-frequency", &i2c_imx->bitrate);
if (ret < 0 && pdata && 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 */
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)
ret = i2c_imx_init_recovery_info(i2c_imx, pdev);
/* Give it another chance if pinctrl used is not ready yet */
if (ret == -EPROBE_DEFER)
goto rpm_disable;
goto clk_notifier_unregister;

/* Add I2C adapter */
ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
if (ret < 0)
goto rpm_disable;
goto clk_notifier_unregister;

pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
@@ -1162,6 +1177,8 @@ static int i2c_imx_probe(struct platform_device *pdev)

return 0; /* Return OK */

clk_notifier_unregister:
clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
rpm_disable:
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
@@ -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_I2SR);

clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
clk_disable_unprepare(i2c_imx->clk);

pm_runtime_put_noidle(&pdev->dev);
@@ -1208,7 +1226,7 @@ static int i2c_imx_runtime_suspend(struct device *dev)
{
struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);

clk_disable_unprepare(i2c_imx->clk);
clk_disable(i2c_imx->clk);

return 0;
}
@@ -1218,7 +1236,7 @@ static int i2c_imx_runtime_resume(struct device *dev)
struct imx_i2c_struct *i2c_imx = dev_get_drvdata(dev);
int ret;

ret = clk_prepare_enable(i2c_imx->clk);
ret = clk_enable(i2c_imx->clk);
if (ret)
dev_err(dev, "can't enable I2C clock, ret=%d\n", ret);

8 changes: 6 additions & 2 deletions drivers/i2c/busses/i2c-mv64xxx.c
Original file line number Diff line number Diff line change
@@ -845,12 +845,16 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
*/
if (of_device_is_compatible(np, "marvell,mv78230-i2c")) {
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")) {
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"))
Loading
Oops, something went wrong.

0 comments on commit 0d5b1bd

Please sign in to comment.