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,11 +845,15 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, ...@@ -845,11 +845,15 @@ 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;
/* The delay is only needed in standard mode (100kHz) */
if (bus_freq <= 100000)
drv_data->errata_delay = true; 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;
/* The delay is only needed in standard mode (100kHz) */
if (bus_freq <= 100000)
drv_data->errata_delay = true; drv_data->errata_delay = true;
} }
......
...@@ -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;
if (platform_data) {
i2c->adap.timeout = platform_data->timeout;
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); i2c->gpio = devm_gpiod_get_optional(&pdev->dev, "reset-gpios", GPIOD_OUT_LOW);
if (IS_ERR(i2c->gpio)) if (IS_ERR(i2c->gpio))
return PTR_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->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; i2c->algo_data.i2c_clock = 59000;
i2c->gpio = NULL;
if (platform_data) {
i2c->adap.timeout = platform_data->timeout;
i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed;
} }
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,
"sb800_piix4_smb")) {
release_region(piix4_smba, SMBIOSIZE);
return -EBUSY;
}
outb_p(SB800_PIIX4_PORT_IDX_SEL, SB800_PIIX4_SMB_IDX); outb_p(SB800_PIIX4_PORT_IDX_SEL, SB800_PIIX4_SMB_IDX);
port_sel = inb_p(SB800_PIIX4_SMB_IDX + 1); port_sel = inb_p(SB800_PIIX4_SMB_IDX + 1);
piix4_port_sel_sb800 = (port_sel & 0x01) ? piix4_port_sel_sb800 = (port_sel & 0x01) ?
...@@ -381,7 +389,7 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, ...@@ -381,7 +389,7 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
SB800_PIIX4_PORT_IDX; SB800_PIIX4_PORT_IDX;
piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK; piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK;
piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT; piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT;
mutex_unlock(&piix4_mutex_sb800); release_region(SB800_PIIX4_SMB_IDX, 2);
} }
dev_info(&PIIX4_dev->dev, dev_info(&PIIX4_dev->dev,
...@@ -462,13 +470,13 @@ static int piix4_transaction(struct i2c_adapter *piix4_adapter) ...@@ -462,13 +470,13 @@ static int piix4_transaction(struct i2c_adapter *piix4_adapter)
/* We will always wait for a fraction of a second! (See PIIX4 docs errata) */ /* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
if (srvrworks_csb5_delay) /* Extra delay for SERVERWORKS_CSB5 */ if (srvrworks_csb5_delay) /* Extra delay for SERVERWORKS_CSB5 */
msleep(2); usleep_range(2000, 2100);
else else
msleep(1); usleep_range(250, 500);
while ((++timeout < MAX_TIMEOUT) && while ((++timeout < MAX_TIMEOUT) &&
((temp = inb_p(SMBHSTSTS)) & 0x01)) ((temp = inb_p(SMBHSTSTS)) & 0x01))
msleep(1); usleep_range(250, 500);
/* If the SMBus is still busy, we give up */ /* If the SMBus is still busy, we give up */
if (timeout == MAX_TIMEOUT) { if (timeout == MAX_TIMEOUT) {
...@@ -679,7 +687,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, ...@@ -679,7 +687,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
u8 port; u8 port;
int retval; int retval;
mutex_lock(&piix4_mutex_sb800); if (!request_muxed_region(SB800_PIIX4_SMB_IDX, 2, "sb800_piix4_smb"))
return -EBUSY;
/* Request the SMBUS semaphore, avoid conflicts with the IMC */ /* Request the SMBUS semaphore, avoid conflicts with the IMC */
smbslvcnt = inb_p(SMBSLVCNT); smbslvcnt = inb_p(SMBSLVCNT);
...@@ -695,8 +704,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, ...@@ -695,8 +704,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
} while (--retries); } while (--retries);
/* SMBus is still owned by the IMC, we give up */ /* SMBus is still owned by the IMC, we give up */
if (!retries) { if (!retries) {
mutex_unlock(&piix4_mutex_sb800); retval = -EBUSY;
return -EBUSY; goto release;
} }
/* /*
...@@ -753,8 +762,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, ...@@ -753,8 +762,8 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
if ((size == I2C_SMBUS_BLOCK_DATA) && adapdata->notify_imc) if ((size == I2C_SMBUS_BLOCK_DATA) && adapdata->notify_imc)
piix4_imc_wakeup(); piix4_imc_wakeup();
mutex_unlock(&piix4_mutex_sb800); release:
release_region(SB800_PIIX4_SMB_IDX, 2);
return retval; return retval;
} }
...@@ -899,13 +908,6 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -899,13 +908,6 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
bool notify_imc = false; bool notify_imc = false;
is_sb800 = true; is_sb800 = true;
if (!request_region(SB800_PIIX4_SMB_IDX, 2, "smba_idx")) {
dev_err(&dev->dev,
"SMBus base address index region 0x%x already in use!\n",
SB800_PIIX4_SMB_IDX);
return -EBUSY;
}
if (dev->vendor == PCI_VENDOR_ID_AMD && if (dev->vendor == PCI_VENDOR_ID_AMD &&
dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) { dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) {
u8 imc; u8 imc;
...@@ -922,20 +924,16 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -922,20 +924,16 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
/* base address location etc changed in SB800 */ /* base address location etc changed in SB800 */
retval = piix4_setup_sb800(dev, id, 0); retval = piix4_setup_sb800(dev, id, 0);
if (retval < 0) { if (retval < 0)
release_region(SB800_PIIX4_SMB_IDX, 2);
return retval; return retval;
}
/* /*
* Try to register multiplexed main SMBus adapter, * Try to register multiplexed main SMBus adapter,
* give up if we can't * give up if we can't
*/ */
retval = piix4_add_adapters_sb800(dev, retval, notify_imc); retval = piix4_add_adapters_sb800(dev, retval, notify_imc);
if (retval < 0) { if (retval < 0)
release_region(SB800_PIIX4_SMB_IDX, 2);
return retval; return retval;
}
} else { } else {
retval = piix4_setup(dev, id); retval = piix4_setup(dev, id);
if (retval < 0) if (retval < 0)
...@@ -983,11 +981,8 @@ static void piix4_adap_remove(struct i2c_adapter *adap) ...@@ -983,11 +981,8 @@ static void piix4_adap_remove(struct i2c_adapter *adap)
if (adapdata->smba) { if (adapdata->smba) {
i2c_del_adapter(adap); i2c_del_adapter(adap);
if (adapdata->port == (0 << piix4_port_shift_sb800)) { if (adapdata->port == (0 << piix4_port_shift_sb800))
release_region(adapdata->smba, SMBIOSIZE); release_region(adapdata->smba, SMBIOSIZE);
if (adapdata->sb800_main)
release_region(SB800_PIIX4_SMB_IDX, 2);
}
kfree(adapdata); kfree(adapdata);
kfree(adap); kfree(adap);
} }
......
This diff is collapsed.
...@@ -102,8 +102,8 @@ ...@@ -102,8 +102,8 @@
#define RCAR_IRQ_RECV (MNR | MAL | MST | MAT | MDR) #define RCAR_IRQ_RECV (MNR | MAL | MST | MAT | MDR)
#define RCAR_IRQ_STOP (MST) #define RCAR_IRQ_STOP (MST)
#define RCAR_IRQ_ACK_SEND (~(MAT | MDE) & 0xFF) #define RCAR_IRQ_ACK_SEND (~(MAT | MDE) & 0x7F)
#define RCAR_IRQ_ACK_RECV (~(MAT | MDR) & 0xFF) #define RCAR_IRQ_ACK_RECV (~(MAT | MDR) & 0x7F)
#define ID_LAST_MSG (1 << 0) #define ID_LAST_MSG (1 << 0)
#define ID_FIRST_MSG (1 << 1) #define ID_FIRST_MSG (1 << 1)
......
...@@ -182,7 +182,8 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, ...@@ -182,7 +182,8 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
status = acpi_evaluate_object(smbus_cmi->handle, method, &input, status = acpi_evaluate_object(smbus_cmi->handle, method, &input,
&buffer); &buffer);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, "Evaluating %s: %i", method, status)); acpi_handle_err(smbus_cmi->handle,
"Failed to evaluate %s: %i\n", method, status);
return -EIO; return -EIO;
} }
...@@ -190,19 +191,19 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, ...@@ -190,19 +191,19 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
if (pkg && pkg->type == ACPI_TYPE_PACKAGE) if (pkg && pkg->type == ACPI_TYPE_PACKAGE)
obj = pkg->package.elements; obj = pkg->package.elements;
else { else {
ACPI_ERROR((AE_INFO, "Invalid argument type")); acpi_handle_err(smbus_cmi->handle, "Invalid argument type\n");
result = -EIO; result = -EIO;
goto out; goto out;
} }
if (obj == NULL || obj->type != ACPI_TYPE_INTEGER) { if (obj == NULL || obj->type != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO, "Invalid argument type")); acpi_handle_err(smbus_cmi->handle, "Invalid argument type\n");
result = -EIO; result = -EIO;
goto out; goto out;
} }
result = obj->integer.value; result = obj->integer.value;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s return status: %i\n", acpi_handle_debug(smbus_cmi->handle, "%s return status: %i\n", method,
method, result)); result);
switch (result) { switch (result) {
case ACPI_SMBUS_STATUS_OK: case ACPI_SMBUS_STATUS_OK:
...@@ -227,7 +228,7 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, ...@@ -227,7 +228,7 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
obj = pkg->package.elements + 1; obj = pkg->package.elements + 1;
if (obj->type != ACPI_TYPE_INTEGER) { if (obj->type != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO, "Invalid argument type")); acpi_handle_err(smbus_cmi->handle, "Invalid argument type\n");
result = -EIO; result = -EIO;
goto out; goto out;
} }
...@@ -239,7 +240,8 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, ...@@ -239,7 +240,8 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
case I2C_SMBUS_BYTE_DATA: case I2C_SMBUS_BYTE_DATA:
case I2C_SMBUS_WORD_DATA: case I2C_SMBUS_WORD_DATA:
if (obj->type != ACPI_TYPE_INTEGER) { if (obj->type != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO, "Invalid argument type")); acpi_handle_err(smbus_cmi->handle,
"Invalid argument type\n");
result = -EIO; result = -EIO;
goto out; goto out;
} }
...@@ -250,7 +252,8 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, ...@@ -250,7 +252,8 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags,
break; break;
case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_BLOCK_DATA:
if (obj->type != ACPI_TYPE_BUFFER) { if (obj->type != ACPI_TYPE_BUFFER) {
ACPI_ERROR((AE_INFO, "Invalid argument type")); acpi_handle_err(smbus_cmi->handle,
"Invalid argument type\n");
result = -EIO; result = -EIO;
goto out; goto out;
} }
...@@ -300,6 +303,7 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi, ...@@ -300,6 +303,7 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi,
const char *name) const char *name)
{ {
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_handle *handle = smbus_cmi->handle;
union acpi_object *obj; union acpi_object *obj;
acpi_status status; acpi_status status;
...@@ -308,8 +312,8 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi, ...@@ -308,8 +312,8 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi,
smbus_cmi->methods->mt_info, smbus_cmi->methods->mt_info,
NULL, &buffer); NULL, &buffer);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, "Evaluating %s: %i", acpi_handle_err(handle, "Failed to evaluate %s: %i\n",
smbus_cmi->methods->mt_info, status)); smbus_cmi->methods->mt_info, status);
return -EIO; return -EIO;
} }
...@@ -317,18 +321,18 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi, ...@@ -317,18 +321,18 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi,
if (obj && obj->type == ACPI_TYPE_PACKAGE) if (obj && obj->type == ACPI_TYPE_PACKAGE)
obj = obj->package.elements; obj = obj->package.elements;
else { else {
ACPI_ERROR((AE_INFO, "Invalid argument type")); acpi_handle_err(handle, "Invalid argument type\n");
kfree(buffer.pointer); kfree(buffer.pointer);
return -EIO; return -EIO;
} }
if (obj->type != ACPI_TYPE_INTEGER) { if (obj->type != ACPI_TYPE_INTEGER) {
ACPI_ERROR((AE_INFO, "Invalid argument type")); acpi_handle_err(handle, "Invalid argument type\n");
kfree(buffer.pointer); kfree(buffer.pointer);
return -EIO; return -EIO;
} else } else
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SMBus CMI Version %x" acpi_handle_debug(handle, "SMBus CMI Version %x\n",
"\n", (int)obj->integer.value)); (int)obj->integer.value);
kfree(buffer.pointer); kfree(buffer.pointer);
smbus_cmi->cap_info = 1; smbus_cmi->cap_info = 1;
...@@ -337,8 +341,7 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi, ...@@ -337,8 +341,7 @@ static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi,
else if (!strcmp(name, smbus_cmi->methods->mt_sbw)) else if (!strcmp(name, smbus_cmi->methods->mt_sbw))
smbus_cmi->cap_write = 1; smbus_cmi->cap_write = 1;
else else
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported CMI method: %s\n", acpi_handle_debug(handle, "Unsupported CMI method: %s\n", name);
name));
return 0; return 0;
} }
......
...@@ -349,7 +349,7 @@ static void stm32f4_i2c_read_msg(struct stm32f4_i2c_dev *i2c_dev) ...@@ -349,7 +349,7 @@ static void stm32f4_i2c_read_msg(struct stm32f4_i2c_dev *i2c_dev)
static void stm32f4_i2c_terminate_xfer(struct stm32f4_i2c_dev *i2c_dev) static void stm32f4_i2c_terminate_xfer(struct stm32f4_i2c_dev *i2c_dev)
{ {
struct stm32f4_i2c_msg *msg = &i2c_dev->msg; struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2; void __iomem *reg;
stm32f4_i2c_disable_irq(i2c_dev); stm32f4_i2c_disable_irq(i2c_dev);
......
This diff is collapsed.
...@@ -851,7 +851,7 @@ static const struct of_device_id xiic_of_match[] = { ...@@ -851,7 +851,7 @@ static const struct of_device_id xiic_of_match[] = {
MODULE_DEVICE_TABLE(of, xiic_of_match); MODULE_DEVICE_TABLE(of, xiic_of_match);
#endif #endif
static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev) static int __maybe_unused xiic_i2c_runtime_suspend(struct device *dev)
{ {
struct xiic_i2c *i2c = dev_get_drvdata(dev); struct xiic_i2c *i2c = dev_get_drvdata(dev);
...@@ -860,7 +860,7 @@ static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev) ...@@ -860,7 +860,7 @@ static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev)
return 0; return 0;
} }
static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev) static int __maybe_unused xiic_i2c_runtime_resume(struct device *dev)
{ {
struct xiic_i2c *i2c = dev_get_drvdata(dev); struct xiic_i2c *i2c = dev_get_drvdata(dev);
int ret; int ret;
...@@ -875,8 +875,8 @@ static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev) ...@@ -875,8 +875,8 @@ static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev)
} }
static const struct dev_pm_ops xiic_dev_pm_ops = { static const struct dev_pm_ops xiic_dev_pm_ops = {
SET_RUNTIME_PM_OPS(cdns_i2c_runtime_suspend, SET_RUNTIME_PM_OPS(xiic_i2c_runtime_suspend,
cdns_i2c_runtime_resume, NULL) xiic_i2c_runtime_resume, NULL)
}; };
static struct platform_driver xiic_i2c_driver = { static struct platform_driver xiic_i2c_driver = {
.probe = xiic_i2c_probe, .probe = xiic_i2c_probe,
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/delay.h>
#define XLP9XX_I2C_DIV 0x0 #define XLP9XX_I2C_DIV 0x0
#define XLP9XX_I2C_CTRL 0x1 #define XLP9XX_I2C_CTRL 0x1
...@@ -36,6 +37,8 @@ ...@@ -36,6 +37,8 @@
#define XLP9XX_I2C_TIMEOUT 0X10 #define XLP9XX_I2C_TIMEOUT 0X10
#define XLP9XX_I2C_GENCALLADDR 0x11 #define XLP9XX_I2C_GENCALLADDR 0x11
#define XLP9XX_I2C_STATUS_BUSY BIT(0)
#define XLP9XX_I2C_CMD_START BIT(7) #define XLP9XX_I2C_CMD_START BIT(7)
#define XLP9XX_I2C_CMD_STOP BIT(6) #define XLP9XX_I2C_CMD_STOP BIT(6)
#define XLP9XX_I2C_CMD_READ BIT(5) #define XLP9XX_I2C_CMD_READ BIT(5)
...@@ -71,6 +74,7 @@ ...@@ -71,6 +74,7 @@
#define XLP9XX_I2C_HIGH_FREQ 400000 #define XLP9XX_I2C_HIGH_FREQ 400000
#define XLP9XX_I2C_FIFO_SIZE 0x80U #define XLP9XX_I2C_FIFO_SIZE 0x80U
#define XLP9XX_I2C_TIMEOUT_MS 1000 #define XLP9XX_I2C_TIMEOUT_MS 1000
#define XLP9XX_I2C_BUSY_TIMEOUT 50
#define XLP9XX_I2C_FIFO_WCNT_MASK 0xff #define XLP9XX_I2C_FIFO_WCNT_MASK 0xff
#define XLP9XX_I2C_STATUS_ERRMASK (XLP9XX_I2C_INTEN_ARLOST | \ #define XLP9XX_I2C_STATUS_ERRMASK (XLP9XX_I2C_INTEN_ARLOST | \
...@@ -125,7 +129,16 @@ static void xlp9xx_i2c_update_rx_fifo_thres(struct xlp9xx_i2c_dev *priv) ...@@ -125,7 +129,16 @@ static void xlp9xx_i2c_update_rx_fifo_thres(struct xlp9xx_i2c_dev *priv)
{ {
u32 thres; u32 thres;
thres = min(priv->msg_buf_remaining, XLP9XX_I2C_FIFO_SIZE); if (priv->len_recv)
/* interrupt after the first read to examine
* the length byte before proceeding further
*/
thres = 1;
else if (priv->msg_buf_remaining > XLP9XX_I2C_FIFO_SIZE)
thres = XLP9XX_I2C_FIFO_SIZE;
else
thres = priv->msg_buf_remaining;
xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_MFIFOCTRL, xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_MFIFOCTRL,
thres << XLP9XX_I2C_MFIFOCTRL_HITH_SHIFT); thres << XLP9XX_I2C_MFIFOCTRL_HITH_SHIFT);
} }
...@@ -144,7 +157,7 @@ static void xlp9xx_i2c_fill_tx_fifo(struct xlp9xx_i2c_dev *priv) ...@@ -144,7 +157,7 @@ static void xlp9xx_i2c_fill_tx_fifo(struct xlp9xx_i2c_dev *priv)
static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv) static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)
{ {
u32 len, i; u32 len, i, val;
u8 rlen, *buf = priv->msg_buf; u8 rlen, *buf = priv->msg_buf;
len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) & len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) &
...@@ -156,19 +169,27 @@ static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv) ...@@ -156,19 +169,27 @@ static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)
rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
*buf++ = rlen; *buf++ = rlen;
len--; len--;
if (priv->client_pec) if (priv->client_pec)
++rlen; ++rlen;
/* update remaining bytes and message length */ /* update remaining bytes and message length */
priv->msg_buf_remaining = rlen; priv->msg_buf_remaining = rlen;
priv->msg_len = rlen + 1; priv->msg_len = rlen + 1;
priv->len_recv = false; priv->len_recv = false;
}
/* Update transfer length to read only actual data */
val = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_CTRL);
val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) |
((rlen + 1) << XLP9XX_I2C_CTRL_MCTLEN_SHIFT);
xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, val);
} else {
len = min(priv->msg_buf_remaining, len); len = min(priv->msg_buf_remaining, len);
for (i = 0; i < len; i++, buf++) for (i = 0; i < len; i++, buf++)
*buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); *buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
priv->msg_buf_remaining -= len; priv->msg_buf_remaining -= len;
}
priv->msg_buf = buf; priv->msg_buf = buf;
if (priv->msg_buf_remaining) if (priv->msg_buf_remaining)
...@@ -224,6 +245,26 @@ static irqreturn_t xlp9xx_i2c_isr(int irq, void *dev_id) ...@@ -224,6 +245,26 @@ static irqreturn_t xlp9xx_i2c_isr(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int xlp9xx_i2c_check_bus_status(struct xlp9xx_i2c_dev *priv)
{
u32 status;
u32 busy_timeout = XLP9XX_I2C_BUSY_TIMEOUT;
while (busy_timeout) {
status = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_STATUS);
if ((status & XLP9XX_I2C_STATUS_BUSY) == 0)
break;
busy_timeout--;
usleep_range(1000, 1100);
}
if (!busy_timeout)
return -EIO;
return 0;
}
static int xlp9xx_i2c_init(struct xlp9xx_i2c_dev *priv) static int xlp9xx_i2c_init(struct xlp9xx_i2c_dev *priv)
{ {
u32 prescale; u32 prescale;
...@@ -311,7 +352,9 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg, ...@@ -311,7 +352,9 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
/* set cmd reg */ /* set cmd reg */
cmd = XLP9XX_I2C_CMD_START; cmd = XLP9XX_I2C_CMD_START;
cmd |= (priv->msg_read ? XLP9XX_I2C_CMD_READ : XLP9XX_I2C_CMD_WRITE); if (msg->len)
cmd |= (priv->msg_read ?
XLP9XX_I2C_CMD_READ : XLP9XX_I2C_CMD_WRITE);
if (last_msg) if (last_msg)
cmd |= XLP9XX_I2C_CMD_STOP; cmd |= XLP9XX_I2C_CMD_STOP;
...@@ -320,11 +363,12 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg, ...@@ -320,11 +363,12 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
timeleft = msecs_to_jiffies(XLP9XX_I2C_TIMEOUT_MS); timeleft = msecs_to_jiffies(XLP9XX_I2C_TIMEOUT_MS);
timeleft = wait_for_completion_timeout(&priv->msg_complete, timeleft); timeleft = wait_for_completion_timeout(&priv->msg_complete, timeleft);
if (priv->msg_err) { if (priv->msg_err & XLP9XX_I2C_INTEN_BUSERR) {
dev_dbg(priv->dev, "transfer error %x!\n", priv->msg_err); dev_dbg(priv->dev, "transfer error %x!\n", priv->msg_err);
if (priv->msg_err & XLP9XX_I2C_INTEN_BUSERR) xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CMD, XLP9XX_I2C_CMD_STOP);
xlp9xx_i2c_init(priv);
return -EIO; return -EIO;
} else if (priv->msg_err & XLP9XX_I2C_INTEN_NACKADDR) {
return -ENXIO;
} }
if (timeleft == 0) { if (timeleft == 0) {
...@@ -345,6 +389,14 @@ static int xlp9xx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ...@@ -345,6 +389,14 @@ static int xlp9xx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int i, ret; int i, ret;
struct xlp9xx_i2c_dev *priv = i2c_get_adapdata(adap); struct xlp9xx_i2c_dev *priv = i2c_get_adapdata(adap);
ret = xlp9xx_i2c_check_bus_status(priv);
if (ret) {
xlp9xx_i2c_init(priv);
ret = xlp9xx_i2c_check_bus_status(priv);
if (ret)
return ret;
}
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
ret = xlp9xx_i2c_xfer_msg(priv, &msgs[i], i == num - 1); ret = xlp9xx_i2c_xfer_msg(priv, &msgs[i], i == num - 1);
if (ret != 0) if (ret != 0)
...@@ -356,8 +408,8 @@ static int xlp9xx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ...@@ -356,8 +408,8 @@ static int xlp9xx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
static u32 xlp9xx_i2c_functionality(struct i2c_adapter *adapter) static u32 xlp9xx_i2c_functionality(struct i2c_adapter *adapter)
{ {
return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_READ_BLOCK_DATA |
I2C_FUNC_10BIT_ADDR; I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR;
} }
static const struct i2c_algorithm xlp9xx_i2c_algo = { static const struct i2c_algorithm xlp9xx_i2c_algo = {
......
...@@ -58,6 +58,8 @@ ...@@ -58,6 +58,8 @@
#define I2C_ADDR_7BITS_MAX 0x77 #define I2C_ADDR_7BITS_MAX 0x77
#define I2C_ADDR_7BITS_COUNT (I2C_ADDR_7BITS_MAX + 1) #define I2C_ADDR_7BITS_COUNT (I2C_ADDR_7BITS_MAX + 1)
#define I2C_ADDR_DEVICE_ID 0x7c
/* /*
* core_lock protects i2c_adapter_idr, and guarantees that device detection, * core_lock protects i2c_adapter_idr, and guarantees that device detection,
* deletion of detected devices, and attach_adapter calls are serialized * deletion of detected devices, and attach_adapter calls are serialized
...@@ -67,18 +69,18 @@ static DEFINE_IDR(i2c_adapter_idr); ...@@ -67,18 +69,18 @@ static DEFINE_IDR(i2c_adapter_idr);
static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver); static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
static struct static_key i2c_trace_msg = STATIC_KEY_INIT_FALSE; static DEFINE_STATIC_KEY_FALSE(i2c_trace_msg_key);
static bool is_registered; static bool is_registered;
int i2c_transfer_trace_reg(void) int i2c_transfer_trace_reg(void)
{ {
static_key_slow_inc(&i2c_trace_msg); static_branch_inc(&i2c_trace_msg_key);
return 0; return 0;
} }
void i2c_transfer_trace_unreg(void) void i2c_transfer_trace_unreg(void)
{ {
static_key_slow_dec(&i2c_trace_msg); static_branch_dec(&i2c_trace_msg_key);
} }
const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id, const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
...@@ -124,6 +126,10 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) ...@@ -124,6 +126,10 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
int rc; int rc;
rc = of_device_uevent_modalias(dev, env);
if (rc != -ENODEV)
return rc;
rc = acpi_device_uevent_modalias(dev, env); rc = acpi_device_uevent_modalias(dev, env);
if (rc != -ENODEV) if (rc != -ENODEV)
return rc; return rc;
...@@ -439,6 +445,10 @@ show_modalias(struct device *dev, struct device_attribute *attr, char *buf) ...@@ -439,6 +445,10 @@ show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
int len; int len;
len = of_device_modalias(dev, buf, PAGE_SIZE);
if (len != -ENODEV)
return len;
len = acpi_device_modalias(dev, buf, PAGE_SIZE -1); len = acpi_device_modalias(dev, buf, PAGE_SIZE -1);
if (len != -ENODEV) if (len != -ENODEV)
return len; return len;
...@@ -507,7 +517,7 @@ static unsigned short i2c_encode_flags_to_addr(struct i2c_client *client) ...@@ -507,7 +517,7 @@ static unsigned short i2c_encode_flags_to_addr(struct i2c_client *client)
/* This is a permissive address validity check, I2C address map constraints /* This is a permissive address validity check, I2C address map constraints
* are purposely not enforced, except for the general call address. */ * are purposely not enforced, except for the general call address. */
int i2c_check_addr_validity(unsigned addr, unsigned short flags) static int i2c_check_addr_validity(unsigned int addr, unsigned short flags)
{ {
if (flags & I2C_CLIENT_TEN) { if (flags & I2C_CLIENT_TEN) {
/* 10-bit address, all values are valid */ /* 10-bit address, all values are valid */
...@@ -1838,11 +1848,12 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) ...@@ -1838,11 +1848,12 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
if (adap->quirks && i2c_check_for_quirks(adap, msgs, num)) if (adap->quirks && i2c_check_for_quirks(adap, msgs, num))
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* i2c_trace_msg gets enabled when tracepoint i2c_transfer gets /*
* i2c_trace_msg_key gets enabled when tracepoint i2c_transfer gets
* enabled. This is an efficient way of keeping the for-loop from * enabled. This is an efficient way of keeping the for-loop from
* being executed when not needed. * being executed when not needed.
*/ */
if (static_key_false(&i2c_trace_msg)) { if (static_branch_unlikely(&i2c_trace_msg_key)) {
int i; int i;
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
if (msgs[i].flags & I2C_M_RD) if (msgs[i].flags & I2C_M_RD)
...@@ -1861,12 +1872,12 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) ...@@ -1861,12 +1872,12 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
break; break;
} }
if (static_key_false(&i2c_trace_msg)) { if (static_branch_unlikely(&i2c_trace_msg_key)) {
int i; int i;
for (i = 0; i < ret; i++) for (i = 0; i < ret; i++)
if (msgs[i].flags & I2C_M_RD) if (msgs[i].flags & I2C_M_RD)
trace_i2c_reply(adap, &msgs[i], i); trace_i2c_reply(adap, &msgs[i], i);
trace_i2c_result(adap, i, ret); trace_i2c_result(adap, num, ret);
} }
return ret; return ret;
...@@ -1968,6 +1979,37 @@ int i2c_transfer_buffer_flags(const struct i2c_client *client, char *buf, ...@@ -1968,6 +1979,37 @@ int i2c_transfer_buffer_flags(const struct i2c_client *client, char *buf,
} }
EXPORT_SYMBOL(i2c_transfer_buffer_flags); EXPORT_SYMBOL(i2c_transfer_buffer_flags);
/**
* i2c_get_device_id - get manufacturer, part id and die revision of a device
* @client: The device to query
* @id: The queried information
*
* Returns negative errno on error, zero on success.
*/
int i2c_get_device_id(const struct i2c_client *client,
struct i2c_device_identity *id)
{
struct i2c_adapter *adap = client->adapter;
union i2c_smbus_data raw_id;
int ret;
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_I2C_BLOCK))
return -EOPNOTSUPP;
raw_id.block[0] = 3;
ret = i2c_smbus_xfer(adap, I2C_ADDR_DEVICE_ID, 0,
I2C_SMBUS_READ, client->addr << 1,
I2C_SMBUS_I2C_BLOCK_DATA, &raw_id);
if (ret)
return ret;
id->manufacturer_id = (raw_id.block[1] << 4) | (raw_id.block[2] >> 4);
id->part_id = ((raw_id.block[2] & 0xf) << 5) | (raw_id.block[3] >> 3);
id->die_revision = raw_id.block[3] & 0x7;
return 0;
}
EXPORT_SYMBOL_GPL(i2c_get_device_id);
/* ---------------------------------------------------- /* ----------------------------------------------------
* the i2c address scanning function * the i2c address scanning function
* Will not work for 10-bit addresses! * Will not work for 10-bit addresses!
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Copyright (C) 2008 Jochen Friedrich <jochen@scram.de> * Copyright (C) 2008 Jochen Friedrich <jochen@scram.de>
* based on a previous patch from Jon Smirl <jonsmirl@gmail.com> * based on a previous patch from Jon Smirl <jonsmirl@gmail.com>
* *
* Copyright (C) 2013 Wolfram Sang <wsa@the-dreams.de> * Copyright (C) 2013, 2018 Wolfram Sang <wsa@the-dreams.de>
* *
* This program is free software; you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License as published by the Free
...@@ -25,12 +25,11 @@ ...@@ -25,12 +25,11 @@
static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
struct device_node *node) struct device_node *node)
{ {
struct i2c_client *result; struct i2c_client *client;
struct i2c_board_info info = {}; struct i2c_board_info info = {};
struct dev_archdata dev_ad = {}; struct dev_archdata dev_ad = {};
const __be32 *addr_be;
u32 addr; u32 addr;
int len; int ret;
dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node); dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node);
...@@ -40,13 +39,12 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, ...@@ -40,13 +39,12 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
addr_be = of_get_property(node, "reg", &len); ret = of_property_read_u32(node, "reg", &addr);
if (!addr_be || (len < sizeof(*addr_be))) { if (ret) {
dev_err(&adap->dev, "of_i2c: invalid reg on %pOF\n", node); dev_err(&adap->dev, "of_i2c: invalid reg on %pOF\n", node);
return ERR_PTR(-EINVAL); return ERR_PTR(ret);
} }
addr = be32_to_cpup(addr_be);
if (addr & I2C_TEN_BIT_ADDRESS) { if (addr & I2C_TEN_BIT_ADDRESS) {
addr &= ~I2C_TEN_BIT_ADDRESS; addr &= ~I2C_TEN_BIT_ADDRESS;
info.flags |= I2C_CLIENT_TEN; info.flags |= I2C_CLIENT_TEN;
...@@ -57,15 +55,9 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, ...@@ -57,15 +55,9 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
info.flags |= I2C_CLIENT_SLAVE; info.flags |= I2C_CLIENT_SLAVE;
} }
if (i2c_check_addr_validity(addr, info.flags)) {
dev_err(&adap->dev, "of_i2c: invalid addr=%x on %pOF\n",
addr, node);
return ERR_PTR(-EINVAL);
}
info.addr = addr; info.addr = addr;
info.of_node = of_node_get(node);
info.archdata = &dev_ad; info.archdata = &dev_ad;
info.of_node = of_node_get(node);
if (of_property_read_bool(node, "host-notify")) if (of_property_read_bool(node, "host-notify"))
info.flags |= I2C_CLIENT_HOST_NOTIFY; info.flags |= I2C_CLIENT_HOST_NOTIFY;
...@@ -73,13 +65,13 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, ...@@ -73,13 +65,13 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
if (of_get_property(node, "wakeup-source", NULL)) if (of_get_property(node, "wakeup-source", NULL))
info.flags |= I2C_CLIENT_WAKE; info.flags |= I2C_CLIENT_WAKE;
result = i2c_new_device(adap, &info); client = i2c_new_device(adap, &info);
if (result == NULL) { if (!client) {
dev_err(&adap->dev, "of_i2c: Failure registering %pOF\n", node); dev_err(&adap->dev, "of_i2c: Failure registering %pOF\n", node);
of_node_put(node); of_node_put(node);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
return result; return client;
} }
void of_i2c_register_devices(struct i2c_adapter *adap) void of_i2c_register_devices(struct i2c_adapter *adap)
...@@ -103,7 +95,7 @@ void of_i2c_register_devices(struct i2c_adapter *adap) ...@@ -103,7 +95,7 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
client = of_i2c_register_device(adap, node); client = of_i2c_register_device(adap, node);
if (IS_ERR(client)) { if (IS_ERR(client)) {
dev_warn(&adap->dev, dev_err(&adap->dev,
"Failed to create I2C device for %pOF\n", "Failed to create I2C device for %pOF\n",
node); node);
of_node_clear_flag(node, OF_POPULATED); of_node_clear_flag(node, OF_POPULATED);
......
...@@ -308,17 +308,21 @@ static void i2c_smbus_try_get_dmabuf(struct i2c_msg *msg, u8 init_val) ...@@ -308,17 +308,21 @@ static void i2c_smbus_try_get_dmabuf(struct i2c_msg *msg, u8 init_val)
msg->buf[0] = init_val; msg->buf[0] = init_val;
} }
/* Simulate a SMBus command using the i2c protocol /*
No checking of parameters is done! */ * Simulate a SMBus command using the I2C protocol.
* No checking of parameters is done!
*/
static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
unsigned short flags, unsigned short flags,
char read_write, u8 command, int size, char read_write, u8 command, int size,
union i2c_smbus_data *data) union i2c_smbus_data *data)
{ {
/* So we need to generate a series of msgs. In the case of writing, we /*
need to use only one message; when reading, we need two. We initialize * So we need to generate a series of msgs. In the case of writing, we
most things with sane defaults, to keep the code below somewhat * need to use only one message; when reading, we need two. We
simpler. */ * initialize most things with sane defaults, to keep the code below
* somewhat simpler.
*/
unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3]; unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];
unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2]; unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];
int num = read_write == I2C_SMBUS_READ ? 2 : 1; int num = read_write == I2C_SMBUS_READ ? 2 : 1;
......
...@@ -27,7 +27,6 @@ extern struct rw_semaphore __i2c_board_lock; ...@@ -27,7 +27,6 @@ extern struct rw_semaphore __i2c_board_lock;
extern struct list_head __i2c_board_list; extern struct list_head __i2c_board_list;
extern int __i2c_first_dynamic_bus_num; extern int __i2c_first_dynamic_bus_num;
int i2c_check_addr_validity(unsigned addr, unsigned short flags);
int i2c_check_7bit_addr_validity_strict(unsigned short addr); int i2c_check_7bit_addr_validity_strict(unsigned short addr);
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
......
...@@ -77,6 +77,7 @@ struct chip_desc { ...@@ -77,6 +77,7 @@ struct chip_desc {
pca954x_ismux = 0, pca954x_ismux = 0,
pca954x_isswi pca954x_isswi
} muxtype; } muxtype;
struct i2c_device_identity id;
}; };
struct pca954x { struct pca954x {
...@@ -97,59 +98,83 @@ static const struct chip_desc chips[] = { ...@@ -97,59 +98,83 @@ static const struct chip_desc chips[] = {
.nchans = 2, .nchans = 2,
.enable = 0x4, .enable = 0x4,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9542] = { [pca_9542] = {
.nchans = 2, .nchans = 2,
.enable = 0x4, .enable = 0x4,
.has_irq = 1, .has_irq = 1,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9543] = { [pca_9543] = {
.nchans = 2, .nchans = 2,
.has_irq = 1, .has_irq = 1,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9544] = { [pca_9544] = {
.nchans = 4, .nchans = 4,
.enable = 0x4, .enable = 0x4,
.has_irq = 1, .has_irq = 1,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9545] = { [pca_9545] = {
.nchans = 4, .nchans = 4,
.has_irq = 1, .has_irq = 1,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9546] = { [pca_9546] = {
.nchans = 4, .nchans = 4,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9547] = { [pca_9547] = {
.nchans = 8, .nchans = 8,
.enable = 0x8, .enable = 0x8,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9548] = { [pca_9548] = {
.nchans = 8, .nchans = 8,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9846] = { [pca_9846] = {
.nchans = 4, .nchans = 4,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = {
.manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS,
.part_id = 0x10b,
},
}, },
[pca_9847] = { [pca_9847] = {
.nchans = 8, .nchans = 8,
.enable = 0x8, .enable = 0x8,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = {
.manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS,
.part_id = 0x108,
},
}, },
[pca_9848] = { [pca_9848] = {
.nchans = 8, .nchans = 8,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = {
.manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS,
.part_id = 0x10a,
},
}, },
[pca_9849] = { [pca_9849] = {
.nchans = 4, .nchans = 4,
.enable = 0x4, .enable = 0x4,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = {
.manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS,
.part_id = 0x109,
},
}, },
}; };
...@@ -369,6 +394,30 @@ static int pca954x_probe(struct i2c_client *client, ...@@ -369,6 +394,30 @@ static int pca954x_probe(struct i2c_client *client,
if (IS_ERR(gpio)) if (IS_ERR(gpio))
return PTR_ERR(gpio); return PTR_ERR(gpio);
match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev);
if (match)
data->chip = of_device_get_match_data(&client->dev);
else
data->chip = &chips[id->driver_data];
if (data->chip->id.manufacturer_id != I2C_DEVICE_ID_NONE) {
struct i2c_device_identity id;
ret = i2c_get_device_id(client, &id);
if (ret && ret != -EOPNOTSUPP)
return ret;
if (!ret &&
(id.manufacturer_id != data->chip->id.manufacturer_id ||
id.part_id != data->chip->id.part_id)) {
dev_warn(&client->dev,
"unexpected device id %03x-%03x-%x\n",
id.manufacturer_id, id.part_id,
id.die_revision);
return -ENODEV;
}
}
/* Write the mux register at addr to verify /* Write the mux register at addr to verify
* that the mux is in fact present. This also * that the mux is in fact present. This also
* initializes the mux to disconnected state. * initializes the mux to disconnected state.
...@@ -378,12 +427,6 @@ static int pca954x_probe(struct i2c_client *client, ...@@ -378,12 +427,6 @@ static int pca954x_probe(struct i2c_client *client,
return -ENODEV; return -ENODEV;
} }
match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev);
if (match)
data->chip = of_device_get_match_data(&client->dev);
else
data->chip = &chips[id->driver_data];
data->last_chan = 0; /* force the first selection */ data->last_chan = 0; /* force the first selection */
idle_disconnect_dt = of_node && idle_disconnect_dt = of_node &&
......
...@@ -3,9 +3,6 @@ ...@@ -3,9 +3,6 @@
#define I2C_PCA9564_PLATFORM_H #define I2C_PCA9564_PLATFORM_H
struct i2c_pca9564_pf_platform_data { struct i2c_pca9564_pf_platform_data {
int gpio; /* pin to reset chip. driver will work when
* not supplied (negative value), but it
* cannot exit some error conditions then */
int i2c_clock_speed; /* values are defined in linux/i2c-algo-pca.h */ int i2c_clock_speed; /* values are defined in linux/i2c-algo-pca.h */
int timeout; /* timeout in jiffies */ int timeout; /* timeout in jiffies */
}; };
......
...@@ -47,6 +47,7 @@ struct i2c_algorithm; ...@@ -47,6 +47,7 @@ struct i2c_algorithm;
struct i2c_adapter; struct i2c_adapter;
struct i2c_client; struct i2c_client;
struct i2c_driver; struct i2c_driver;
struct i2c_device_identity;
union i2c_smbus_data; union i2c_smbus_data;
struct i2c_board_info; struct i2c_board_info;
enum i2c_slave_event; enum i2c_slave_event;
...@@ -186,8 +187,37 @@ extern s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, ...@@ -186,8 +187,37 @@ extern s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client,
extern s32 extern s32
i2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client, i2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client,
u8 command, u8 length, u8 *values); u8 command, u8 length, u8 *values);
int i2c_get_device_id(const struct i2c_client *client,
struct i2c_device_identity *id);
#endif /* I2C */ #endif /* I2C */
/**
* struct i2c_device_identity - i2c client device identification
* @manufacturer_id: 0 - 4095, database maintained by NXP
* @part_id: 0 - 511, according to manufacturer
* @die_revision: 0 - 7, according to manufacturer
*/
struct i2c_device_identity {
u16 manufacturer_id;
#define I2C_DEVICE_ID_NXP_SEMICONDUCTORS 0
#define I2C_DEVICE_ID_NXP_SEMICONDUCTORS_1 1
#define I2C_DEVICE_ID_NXP_SEMICONDUCTORS_2 2
#define I2C_DEVICE_ID_NXP_SEMICONDUCTORS_3 3
#define I2C_DEVICE_ID_RAMTRON_INTERNATIONAL 4
#define I2C_DEVICE_ID_ANALOG_DEVICES 5
#define I2C_DEVICE_ID_STMICROELECTRONICS 6
#define I2C_DEVICE_ID_ON_SEMICONDUCTOR 7
#define I2C_DEVICE_ID_SPRINTEK_CORPORATION 8
#define I2C_DEVICE_ID_ESPROS_PHOTONICS_AG 9
#define I2C_DEVICE_ID_FUJITSU_SEMICONDUCTOR 10
#define I2C_DEVICE_ID_FLIR 11
#define I2C_DEVICE_ID_O2MICRO 12
#define I2C_DEVICE_ID_ATMEL 13
#define I2C_DEVICE_ID_NONE 0xffff
u16 part_id;
u8 die_revision;
};
enum i2c_alert_protocol { enum i2c_alert_protocol {
I2C_PROTOCOL_SMBUS_ALERT, I2C_PROTOCOL_SMBUS_ALERT,
I2C_PROTOCOL_SMBUS_HOST_NOTIFY, I2C_PROTOCOL_SMBUS_HOST_NOTIFY,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment