summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-02-22 09:02:24 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2021-02-22 09:02:24 -0800
commit32c080c4b5cfadeb1d1d5952840d696d5cda8bb8 (patch)
tree77dfaa7d04c77fb389b4382303b7b3c3b4e8417b
parenta26a9d8ab4f9edbdfb087a563b6613e9970ef0b0 (diff)
parent0b16cfd9e660f59e396ab5f3af7d49e3677e3f9c (diff)
Merge branch 'i2c/for-5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang: - mostly driver updates. Bigger ones for mlxcpld and iproc. But most of them are all over the place. - removal of the efm32, sirf, u300, and zte zx bus drivers because of platform removal. So, we have a pleasant diffstat this time. - first set of cleanups in the I2C core as preparation to increase maximum length of SMBus transfers to 255 (as specified in the new standard). Better documentation of struct i2c_msg and its flags stand out here. - the testunit can now respond to SMBus block process calls which is the testcase when implementing the above new maximum length. * 'i2c/for-5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (62 commits) i2c: remove redundant error print in stm32f7_i2c_probe i2c: testunit: add support for block process calls i2c: busses: Replace spin_lock_irqsave with spin_lock in hard IRQ dt-bindings: eeprom: at24: Document ROHM BR24G01 i2c: i801: Add support for Intel Alder Lake PCH-P i2c: mv64xxx: Fix check for missing clock after adding RPM i2c: mux: mlxcpld: Add callback to notify mux creation completion i2c: mux: mlxcpld: Extend supported mux number i2c: mux: mlxcpld: Extend driver to support word address space devices i2c: mux: mlxcpld: Get rid of adapter numbers enforcement i2c: mux: mlxcpld: Prepare mux selection infrastructure for two-byte support i2c: mux: mlxcpld: Convert driver to platform driver i2c: imx: Synthesize end of transaction events without idle interrupts i2c: i2c-qcom-geni: Add shutdown callback for i2c i2c: mv64xxx: Add runtime PM support i2c: amd-mp2: Remove unused macro i2c: amd-mp2: convert to PCI logging functions i2c: mux: mlxcpld: Move header file out of x86 realm platform/x86: mlxcpld: Update module license i2c: mux: mlxcpld: Update module license ...
-rw-r--r--Documentation/devicetree/bindings/eeprom/at24.yaml9
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-sirf.txt19
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-stu300.txt15
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-zx2967.txt22
-rw-r--r--Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml21
-rw-r--r--Documentation/devicetree/bindings/i2c/renesas,i2c.txt1
-rw-r--r--Documentation/i2c/slave-testunit-backend.rst23
-rw-r--r--drivers/gpio/gpiolib.c4
-rw-r--r--drivers/i2c/algos/i2c-algo-bit.c4
-rw-r--r--drivers/i2c/busses/Kconfig39
-rw-r--r--drivers/i2c/busses/Makefile4
-rw-r--r--drivers/i2c/busses/i2c-amd-mp2-pci.c55
-rw-r--r--drivers/i2c/busses/i2c-amd-mp2-plat.c3
-rw-r--r--drivers/i2c/busses/i2c-amd-mp2.h6
-rw-r--r--drivers/i2c/busses/i2c-bcm-iproc.c254
-rw-r--r--drivers/i2c/busses/i2c-digicolor.c5
-rw-r--r--drivers/i2c/busses/i2c-efm32.c469
-rw-r--r--drivers/i2c/busses/i2c-elektor.c3
-rw-r--r--drivers/i2c/busses/i2c-gpio.c2
-rw-r--r--drivers/i2c/busses/i2c-hix5hd2.c4
-rw-r--r--drivers/i2c/busses/i2c-i801.c17
-rw-r--r--drivers/i2c/busses/i2c-imx.c65
-rw-r--r--drivers/i2c/busses/i2c-jz4780.c5
-rw-r--r--drivers/i2c/busses/i2c-mlxcpld.c97
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c122
-rw-r--r--drivers/i2c/busses/i2c-qcom-geni.c93
-rw-r--r--drivers/i2c/busses/i2c-qup.c2
-rw-r--r--drivers/i2c/busses/i2c-rcar.c66
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c2
-rw-r--r--drivers/i2c/busses/i2c-sirf.c475
-rw-r--r--drivers/i2c/busses/i2c-stm32f7.c6
-rw-r--r--drivers/i2c/busses/i2c-stu300.c1008
-rw-r--r--drivers/i2c/busses/i2c-tegra.c9
-rw-r--r--drivers/i2c/busses/i2c-zx2967.c602
-rw-r--r--drivers/i2c/i2c-core-acpi.c6
-rw-r--r--drivers/i2c/i2c-core-smbus.c46
-rw-r--r--drivers/i2c/i2c-slave-testunit.c12
-rw-r--r--drivers/i2c/i2c-stub.c1
-rw-r--r--drivers/i2c/muxes/i2c-mux-gpio.c112
-rw-r--r--drivers/i2c/muxes/i2c-mux-mlxcpld.c163
-rw-r--r--include/linux/platform_data/mlxcpld.h31
-rw-r--r--include/linux/platform_data/x86/mlxcpld.h52
-rw-r--r--include/uapi/linux/i2c-dev.h25
-rw-r--r--include/uapi/linux/i2c.h128
44 files changed, 906 insertions, 3201 deletions
diff --git a/Documentation/devicetree/bindings/eeprom/at24.yaml b/Documentation/devicetree/bindings/eeprom/at24.yaml
index d5117c638b75..021d8ae42da3 100644
--- a/Documentation/devicetree/bindings/eeprom/at24.yaml
+++ b/Documentation/devicetree/bindings/eeprom/at24.yaml
@@ -96,9 +96,6 @@ properties:
# These are special cases that don't conform to the above pattern.
# Each requires a standard at24 model as fallback.
- items:
- - const: rohm,br24t01
- - const: atmel,24c01
- - items:
- const: nxp,se97b
- const: atmel,24c02
- items:
@@ -113,6 +110,12 @@ properties:
- items:
- const: renesas,r1ex24128
- const: atmel,24c128
+ - items:
+ - const: rohm,br24g01
+ - const: atmel,24c01
+ - items:
+ - const: rohm,br24t01
+ - const: atmel,24c01
label:
description: Descriptive name of the EEPROM.
diff --git a/Documentation/devicetree/bindings/i2c/i2c-sirf.txt b/Documentation/devicetree/bindings/i2c/i2c-sirf.txt
deleted file mode 100644
index 2701eefb00f7..000000000000
--- a/Documentation/devicetree/bindings/i2c/i2c-sirf.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-I2C for SiRFprimaII platforms
-
-Required properties :
-- compatible : Must be "sirf,prima2-i2c"
-- reg: physical base address of the controller and length of memory mapped
- region.
-- interrupts: interrupt number to the cpu.
-
-Optional properties:
-- clock-frequency : Constains desired I2C/HS-I2C bus clock frequency in Hz.
- The absence of the property indicates the default frequency 100 kHz.
-
-Examples :
-
-i2c0: i2c@b00e0000 {
- compatible = "sirf,prima2-i2c";
- reg = <0xb00e0000 0x10000>;
- interrupts = <24>;
-};
diff --git a/Documentation/devicetree/bindings/i2c/i2c-stu300.txt b/Documentation/devicetree/bindings/i2c/i2c-stu300.txt
deleted file mode 100644
index bd81a482634f..000000000000
--- a/Documentation/devicetree/bindings/i2c/i2c-stu300.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-ST Microelectronics DDC I2C
-
-Required properties :
-- compatible : Must be "st,ddci2c"
-- reg: physical base address of the controller and length of memory mapped
- region.
-- interrupts: interrupt number to the cpu.
-- #address-cells = <1>;
-- #size-cells = <0>;
-
-Optional properties:
-- Child nodes conforming to i2c bus binding
-
-Examples :
-
diff --git a/Documentation/devicetree/bindings/i2c/i2c-zx2967.txt b/Documentation/devicetree/bindings/i2c/i2c-zx2967.txt
deleted file mode 100644
index cb806d1ae4c9..000000000000
--- a/Documentation/devicetree/bindings/i2c/i2c-zx2967.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-ZTE zx2967 I2C controller
-
-Required properties:
- - compatible: must be "zte,zx296718-i2c"
- - reg: physical address and length of the device registers
- - interrupts: a single interrupt specifier
- - clocks: clock for the device
- - #address-cells: should be <1>
- - #size-cells: should be <0>
- - clock-frequency: the desired I2C bus clock frequency.
-
-Examples:
-
- i2c@112000 {
- compatible = "zte,zx296718-i2c";
- reg = <0x00112000 0x1000>;
- interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&osc24m>;
- #address-cells = <1>
- #size-cells = <0>;
- clock-frequency = <1600000>;
- };
diff --git a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
index 5b5ae402f97a..eb72dd571def 100644
--- a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
@@ -18,21 +18,14 @@ properties:
- const: allwinner,sun4i-a10-i2c
- const: allwinner,sun6i-a31-i2c
- items:
- - const: allwinner,sun8i-a23-i2c
+ - enum:
+ - allwinner,sun8i-a23-i2c
+ - allwinner,sun8i-a83t-i2c
+ - allwinner,sun50i-a64-i2c
+ - allwinner,sun50i-a100-i2c
+ - allwinner,sun50i-h6-i2c
+ - allwinner,sun50i-h616-i2c
- const: allwinner,sun6i-a31-i2c
- - items:
- - const: allwinner,sun8i-a83t-i2c
- - const: allwinner,sun6i-a31-i2c
- - items:
- - const: allwinner,sun50i-a64-i2c
- - const: allwinner,sun6i-a31-i2c
- - items:
- - const: allwinner,sun50i-a100-i2c
- - const: allwinner,sun6i-a31-i2c
- - items:
- - const: allwinner,sun50i-h6-i2c
- - const: allwinner,sun6i-a31-i2c
-
- const: marvell,mv64xxx-i2c
- const: marvell,mv78230-i2c
- const: marvell,mv78230-a0-i2c
diff --git a/Documentation/devicetree/bindings/i2c/renesas,i2c.txt b/Documentation/devicetree/bindings/i2c/renesas,i2c.txt
index 96d869ac3839..5762d2d1ab9c 100644
--- a/Documentation/devicetree/bindings/i2c/renesas,i2c.txt
+++ b/Documentation/devicetree/bindings/i2c/renesas,i2c.txt
@@ -26,6 +26,7 @@ Required properties:
"renesas,i2c-r8a77980" if the device is a part of a R8A77980 SoC.
"renesas,i2c-r8a77990" if the device is a part of a R8A77990 SoC.
"renesas,i2c-r8a77995" if the device is a part of a R8A77995 SoC.
+ "renesas,i2c-r8a779a0" if the device is a part of a R8A779A0 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.
diff --git a/Documentation/i2c/slave-testunit-backend.rst b/Documentation/i2c/slave-testunit-backend.rst
index 2c38e64f0bac..ecfc2abec32d 100644
--- a/Documentation/i2c/slave-testunit-backend.rst
+++ b/Documentation/i2c/slave-testunit-backend.rst
@@ -22,8 +22,9 @@ Instantiating the device is regular. Example for bus 0, address 0x30:
After that, you will have a write-only device listening. Reads will just return
an 8-bit version number of the testunit. When writing, the device consists of 4
-8-bit registers and all must be written to start a testcase, i.e. you must
-always write 4 bytes to the device. The registers are:
+8-bit registers and, except for some "partial" commands, all registers must be
+written to start a testcase, i.e. you usually write 4 bytes to the device. The
+registers are:
0x00 CMD - which test to trigger
0x01 DATAL - configuration byte 1 for the test
@@ -67,3 +68,21 @@ status word is currently ignored in the Linux Kernel. Example to send a
notification after 10ms:
# i2cset -y 0 0x30 0x02 0x42 0x64 0x01 i
+
+0x03 SMBUS_BLOCK_PROC_CALL (partial command)
+ DATAL - must be '1', i.e. one further byte will be written
+ DATAH - number of bytes to be sent back
+ DELAY - not applicable, partial command!
+
+This test will respond to a block process call as defined by the SMBus
+specification. The one data byte written specifies how many bytes will be sent
+back in the following read transfer. Note that in this read transfer, the
+testunit will prefix the length of the bytes to follow. So, if your host bus
+driver emulates SMBus calls like the majority does, it needs to support the
+I2C_M_RECV_LEN flag of an i2c_msg. This is a good testcase for it. The returned
+data consists of the length first, and then of an array of bytes from length-1
+to 0. Here is an example which emulates i2c_smbus_block_process_call() using
+i2ctransfer (you need i2c-tools v4.2 or later):
+
+# i2ctransfer -y 0 w3@0x30 0x03 0x01 0x10 r?
+0x10 0x0f 0x0e 0x0d 0x0c 0x0b 0x0a 0x09 0x08 0x07 0x06 0x05 0x04 0x03 0x02 0x01 0x00
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 97eec8d8dbdc..844198cb4e31 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -3469,6 +3469,10 @@ EXPORT_SYMBOL_GPL(gpiod_add_lookup_table);
*/
void gpiod_remove_lookup_table(struct gpiod_lookup_table *table)
{
+ /* Nothing to remove */
+ if (!table)
+ return;
+
mutex_lock(&gpio_lookup_lock);
list_del(&table->list);
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index 913db013fe90..fc90293afcbf 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -622,9 +622,7 @@ static int bit_xfer_atomic(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
static u32 bit_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C | I2C_FUNC_NOSTART | I2C_FUNC_SMBUS_EMUL |
- I2C_FUNC_SMBUS_READ_BLOCK_DATA |
- I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+ return I2C_FUNC_I2C | I2C_FUNC_NOSTART | I2C_FUNC_SMBUS_EMUL_ALL |
I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
}
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 8c55faaea0e7..05ebf7546e3f 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -586,13 +586,6 @@ config I2C_DIGICOLOR
This driver can also be built as a module. If so, the module
will be called i2c-digicolor.
-config I2C_EFM32
- tristate "EFM32 I2C controller"
- depends on ARCH_EFM32 || COMPILE_TEST
- help
- This driver supports the i2c block found in Energy Micro's EFM32
- SoCs.
-
config I2C_EG20T
tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) I2C"
depends on PCI && (X86_32 || MIPS || COMPILE_TEST)
@@ -1000,16 +993,6 @@ config I2C_SIMTEC
This driver can also be built as a module. If so, the module
will be called i2c-simtec.
-config I2C_SIRF
- tristate "CSR SiRFprimaII I2C interface"
- depends on ARCH_SIRF || COMPILE_TEST
- help
- If you say yes to this option, support will be included for the
- CSR SiRFprimaII I2C interface.
-
- This driver can also be built as a module. If so, the module
- will be called i2c-sirf.
-
config I2C_SPRD
tristate "Spreadtrum I2C interface"
depends on I2C=y && (ARCH_SPRD || COMPILE_TEST)
@@ -1050,19 +1033,6 @@ config I2C_STM32F7
This driver can also be built as module. If so, the module
will be called i2c-stm32f7.
-config I2C_STU300
- tristate "ST Microelectronics DDC I2C interface"
- depends on MACH_U300 || COMPILE_TEST
- default y if MACH_U300
- help
- If you say yes to this option, support will be included for the
- I2C interface from ST Microelectronics simply called "DDC I2C"
- supporting both I2C and DDC, used in e.g. the U300 series
- mobile platforms.
-
- This driver can also be built as a module. If so, the module
- will be called i2c-stu300.
-
config I2C_SUN6I_P2WI
tristate "Allwinner sun6i internal P2WI controller"
depends on RESET_CONTROLLER
@@ -1401,15 +1371,6 @@ config I2C_OPAL
This driver can also be built as a module. If so, the module will be
called as i2c-opal.
-config I2C_ZX2967
- tristate "ZTE ZX2967 I2C support"
- depends on ARCH_ZX
- default y
- help
- Selecting this option will add ZX2967 I2C driver.
- This driver can also be built as a module. If so, the module will be
- called i2c-zx2967.
-
config I2C_FSI
tristate "FSI I2C driver"
depends on FSI
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 683c49faca05..615f35e3e31f 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -58,7 +58,6 @@ i2c-designware-platform-$(CONFIG_I2C_DESIGNWARE_BAYTRAIL) += i2c-designware-bayt
obj-$(CONFIG_I2C_DESIGNWARE_PCI) += i2c-designware-pci.o
i2c-designware-pci-y := i2c-designware-pcidrv.o
obj-$(CONFIG_I2C_DIGICOLOR) += i2c-digicolor.o
-obj-$(CONFIG_I2C_EFM32) += i2c-efm32.o
obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o
obj-$(CONFIG_I2C_EMEV2) += i2c-emev2.o
obj-$(CONFIG_I2C_EXYNOS5) += i2c-exynos5.o
@@ -99,13 +98,11 @@ obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o
obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
-obj-$(CONFIG_I2C_SIRF) += i2c-sirf.o
obj-$(CONFIG_I2C_SPRD) += i2c-sprd.o
obj-$(CONFIG_I2C_ST) += i2c-st.o
obj-$(CONFIG_I2C_STM32F4) += i2c-stm32f4.o
i2c-stm32f7-drv-objs := i2c-stm32f7.o i2c-stm32.o
obj-$(CONFIG_I2C_STM32F7) += i2c-stm32f7-drv.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
@@ -122,7 +119,6 @@ obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o
obj-$(CONFIG_I2C_XLR) += i2c-xlr.o
obj-$(CONFIG_I2C_XLP9XX) += i2c-xlp9xx.o
obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o
-obj-$(CONFIG_I2C_ZX2967) += i2c-zx2967.o
# External I2C/SMBus adapter drivers
obj-$(CONFIG_I2C_DIOLAN_U2C) += i2c-diolan-u2c.o
diff --git a/drivers/i2c/busses/i2c-amd-mp2-pci.c b/drivers/i2c/busses/i2c-amd-mp2-pci.c
index cd3fd5ee5f65..ce130a821ea5 100644
--- a/drivers/i2c/busses/i2c-amd-mp2-pci.c
+++ b/drivers/i2c/busses/i2c-amd-mp2-pci.c
@@ -30,7 +30,7 @@ static void amd_mp2_c2p_mutex_unlock(struct amd_i2c_common *i2c_common)
struct amd_mp2_dev *privdata = i2c_common->mp2_dev;
if (unlikely(privdata->c2p_lock_busid != i2c_common->bus_id)) {
- dev_warn(ndev_dev(privdata),
+ pci_warn(privdata->pci_dev,
"bus %d attempting to unlock C2P locked by bus %d\n",
i2c_common->bus_id, privdata->c2p_lock_busid);
return;
@@ -59,8 +59,7 @@ int amd_mp2_bus_enable_set(struct amd_i2c_common *i2c_common, bool enable)
struct amd_mp2_dev *privdata = i2c_common->mp2_dev;
union i2c_cmd_base i2c_cmd_base;
- dev_dbg(ndev_dev(privdata), "%s id: %d\n", __func__,
- i2c_common->bus_id);
+ pci_dbg(privdata->pci_dev, "id: %d\n", i2c_common->bus_id);
i2c_cmd_base.ul = 0;
i2c_cmd_base.s.i2c_cmd = enable ? i2c_enable : i2c_disable;
@@ -111,20 +110,19 @@ EXPORT_SYMBOL_GPL(amd_mp2_rw);
static void amd_mp2_pci_check_rw_event(struct amd_i2c_common *i2c_common)
{
struct amd_mp2_dev *privdata = i2c_common->mp2_dev;
+ struct pci_dev *pdev = privdata->pci_dev;
int len = i2c_common->eventval.r.length;
u32 slave_addr = i2c_common->eventval.r.slave_addr;
bool err = false;
if (unlikely(len != i2c_common->msg->len)) {
- dev_err(ndev_dev(privdata),
- "length %d in event doesn't match buffer length %d!\n",
+ pci_err(pdev, "length %d in event doesn't match buffer length %d!\n",
len, i2c_common->msg->len);
err = true;
}
if (unlikely(slave_addr != i2c_common->msg->addr)) {
- dev_err(ndev_dev(privdata),
- "unexpected slave address %x (expected: %x)!\n",
+ pci_err(pdev, "unexpected slave address %x (expected: %x)!\n",
slave_addr, i2c_common->msg->addr);
err = true;
}
@@ -136,13 +134,14 @@ static void amd_mp2_pci_check_rw_event(struct amd_i2c_common *i2c_common)
static void __amd_mp2_process_event(struct amd_i2c_common *i2c_common)
{
struct amd_mp2_dev *privdata = i2c_common->mp2_dev;
+ struct pci_dev *pdev = privdata->pci_dev;
enum status_type sts = i2c_common->eventval.r.status;
enum response_type res = i2c_common->eventval.r.response;
int len = i2c_common->eventval.r.length;
if (res != command_success) {
if (res != command_failed)
- dev_err(ndev_dev(privdata), "invalid response to i2c command!\n");
+ pci_err(pdev, "invalid response to i2c command!\n");
return;
}
@@ -155,32 +154,26 @@ static void __amd_mp2_process_event(struct amd_i2c_common *i2c_common)
privdata->mmio + AMD_C2P_MSG2,
len);
} else if (sts != i2c_readfail_event) {
- dev_err(ndev_dev(privdata),
- "invalid i2c status after read (%d)!\n", sts);
+ pci_err(pdev, "invalid i2c status after read (%d)!\n", sts);
}
break;
case i2c_write:
if (sts == i2c_writecomplete_event)
amd_mp2_pci_check_rw_event(i2c_common);
else if (sts != i2c_writefail_event)
- dev_err(ndev_dev(privdata),
- "invalid i2c status after write (%d)!\n", sts);
+ pci_err(pdev, "invalid i2c status after write (%d)!\n", sts);
break;
case i2c_enable:
if (sts == i2c_busenable_complete)
i2c_common->cmd_success = true;
else if (sts != i2c_busenable_failed)
- dev_err(ndev_dev(privdata),
- "invalid i2c status after bus enable (%d)!\n",
- sts);
+ pci_err(pdev, "invalid i2c status after bus enable (%d)!\n", sts);
break;
case i2c_disable:
if (sts == i2c_busdisable_complete)
i2c_common->cmd_success = true;
else if (sts != i2c_busdisable_failed)
- dev_err(ndev_dev(privdata),
- "invalid i2c status after bus disable (%d)!\n",
- sts);
+ pci_err(pdev, "invalid i2c status after bus disable (%d)!\n", sts);
break;
default:
break;
@@ -190,10 +183,10 @@ static void __amd_mp2_process_event(struct amd_i2c_common *i2c_common)
void amd_mp2_process_event(struct amd_i2c_common *i2c_common)
{
struct amd_mp2_dev *privdata = i2c_common->mp2_dev;
+ struct pci_dev *pdev = privdata->pci_dev;
if (unlikely(i2c_common->reqcmd == i2c_none)) {
- dev_warn(ndev_dev(privdata),
- "received msg but no cmd was sent (bus = %d)!\n",
+ pci_warn(pdev, "received msg but no cmd was sent (bus = %d)!\n",
i2c_common->bus_id);
return;
}
@@ -208,6 +201,7 @@ EXPORT_SYMBOL_GPL(amd_mp2_process_event);
static irqreturn_t amd_mp2_irq_isr(int irq, void *dev)
{
struct amd_mp2_dev *privdata = dev;
+ struct pci_dev *pdev = privdata->pci_dev;
struct amd_i2c_common *i2c_common;
u32 val;
unsigned int bus_id;
@@ -236,8 +230,7 @@ static irqreturn_t amd_mp2_irq_isr(int irq, void *dev)
val = readl(privdata->mmio + AMD_P2C_MSG_INTEN);
if (val != 0) {
writel(0, privdata->mmio + AMD_P2C_MSG_INTEN);
- dev_warn(ndev_dev(privdata),
- "received irq without message\n");
+ pci_warn(pdev, "received irq without message\n");
ret = IRQ_HANDLED;
}
}
@@ -255,13 +248,13 @@ EXPORT_SYMBOL_GPL(amd_mp2_rw_timeout);
int amd_mp2_register_cb(struct amd_i2c_common *i2c_common)
{
struct amd_mp2_dev *privdata = i2c_common->mp2_dev;
+ struct pci_dev *pdev = privdata->pci_dev;
if (i2c_common->bus_id > 1)
return -EINVAL;
if (privdata->busses[i2c_common->bus_id]) {
- dev_err(ndev_dev(privdata),
- "Bus %d already taken!\n", i2c_common->bus_id);
+ pci_err(pdev, "Bus %d already taken!\n", i2c_common->bus_id);
return -EINVAL;
}
@@ -301,13 +294,13 @@ static int amd_mp2_pci_init(struct amd_mp2_dev *privdata,
rc = pcim_enable_device(pci_dev);
if (rc) {
- dev_err(ndev_dev(privdata), "Failed to enable MP2 PCI device\n");
+ pci_err(pci_dev, "Failed to enable MP2 PCI device\n");
goto err_pci_enable;
}
rc = pcim_iomap_regions(pci_dev, 1 << 2, pci_name(pci_dev));
if (rc) {
- dev_err(ndev_dev(privdata), "I/O memory remapping failed\n");
+ pci_err(pci_dev, "I/O memory remapping failed\n");
goto err_pci_enable;
}
privdata->mmio = pcim_iomap_table(pci_dev)[2];
@@ -327,7 +320,7 @@ static int amd_mp2_pci_init(struct amd_mp2_dev *privdata,
rc = devm_request_irq(&pci_dev->dev, pci_dev->irq, amd_mp2_irq_isr,
IRQF_SHARED, dev_name(&pci_dev->dev), privdata);
if (rc)
- dev_err(&pci_dev->dev, "Failure requesting irq %i: %d\n",
+ pci_err(pci_dev, "Failure requesting irq %i: %d\n",
pci_dev->irq, rc);
return rc;
@@ -363,7 +356,7 @@ static int amd_mp2_pci_probe(struct pci_dev *pci_dev,
privdata->probed = true;
- dev_info(&pci_dev->dev, "MP2 device registered.\n");
+ pci_info(pci_dev, "MP2 device registered.\n");
return 0;
}
@@ -397,8 +390,7 @@ static int amd_mp2_pci_suspend(struct device *dev)
ret = pci_save_state(pci_dev);
if (ret) {
- dev_err(ndev_dev(privdata),
- "pci_save_state failed = %d\n", ret);
+ pci_err(pci_dev, "pci_save_state failed = %d\n", ret);
return ret;
}
@@ -417,8 +409,7 @@ static int amd_mp2_pci_resume(struct device *dev)
pci_restore_state(pci_dev);
ret = pci_enable_device(pci_dev);
if (ret < 0) {
- dev_err(ndev_dev(privdata),
- "pci_enable_device failed = %d\n", ret);
+ pci_err(pci_dev, "pci_enable_device failed = %d\n", ret);
return ret;
}
diff --git a/drivers/i2c/busses/i2c-amd-mp2-plat.c b/drivers/i2c/busses/i2c-amd-mp2-plat.c
index 506433bc0ff2..de058671f9b8 100644
--- a/drivers/i2c/busses/i2c-amd-mp2-plat.c
+++ b/drivers/i2c/busses/i2c-amd-mp2-plat.c
@@ -88,8 +88,7 @@ static void i2c_amd_cmd_completion(struct amd_i2c_common *i2c_common)
union i2c_event *event = &i2c_common->eventval;
if (event->r.status == i2c_readcomplete_event)
- dev_dbg(&i2c_dev->pdev->dev, "%s readdata:%*ph\n",
- __func__, event->r.length,
+ dev_dbg(&i2c_dev->pdev->dev, "readdata:%*ph\n", event->r.length,
i2c_common->msg->buf);
complete(&i2c_dev->cmd_complete);
diff --git a/drivers/i2c/busses/i2c-amd-mp2.h b/drivers/i2c/busses/i2c-amd-mp2.h
index 058362edebaa..ddecd0c88656 100644
--- a/drivers/i2c/busses/i2c-amd-mp2.h
+++ b/drivers/i2c/busses/i2c-amd-mp2.h
@@ -185,12 +185,6 @@ struct amd_mp2_dev {
unsigned int probed;
};
-#define ndev_pdev(ndev) ((ndev)->pci_dev)
-#define ndev_name(ndev) pci_name(ndev_pdev(ndev))
-#define ndev_dev(ndev) (&ndev_pdev(ndev)->dev)
-#define work_amd_i2c_common(__work) \
- container_of(__work, struct amd_i2c_common, work.work)
-
/* PCIe communication driver */
int amd_mp2_rw(struct amd_i2c_common *i2c_common, enum i2c_cmd reqcmd);
diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c
index d8295b1c379d..cceaf69279a9 100644
--- a/drivers/i2c/busses/i2c-bcm-iproc.c
+++ b/drivers/i2c/busses/i2c-bcm-iproc.c
@@ -93,6 +93,7 @@
#define S_CMD_STATUS_MASK 0x07
#define S_CMD_STATUS_SUCCESS 0x0
#define S_CMD_STATUS_TIMEOUT 0x5
+#define S_CMD_STATUS_MASTER_ABORT 0x7
#define IE_OFFSET 0x38
#define IE_M_RX_FIFO_FULL_SHIFT 31
@@ -159,6 +160,11 @@
#define IE_S_ALL_INTERRUPT_SHIFT 21
#define IE_S_ALL_INTERRUPT_MASK 0x3f
+/*
+ * It takes ~18us to reading 10bytes of data, hence to keep tasklet
+ * running for less time, max slave read per tasklet is set to 10 bytes.
+ */
+#define MAX_SLAVE_RX_PER_INT 10
enum i2c_slave_read_status {
I2C_SLAVE_RX_FIFO_EMPTY = 0,
@@ -205,8 +211,18 @@ struct bcm_iproc_i2c_dev {
/* bytes that have been read */
unsigned int rx_bytes;
unsigned int thld_bytes;
+
+ bool slave_rx_only;
+ bool rx_start_rcvd;
+ bool slave_read_complete;
+ u32 tx_underrun;
+ u32 slave_int_mask;
+ struct tasklet_struct slave_rx_tasklet;
};
+/* tasklet to process slave rx data */
+static void slave_rx_tasklet_fn(unsigned long);
+
/*
* Can be expanded in the future if more interrupt status bits are utilized
*/
@@ -215,7 +231,8 @@ struct bcm_iproc_i2c_dev {
#define ISR_MASK_SLAVE (BIT(IS_S_START_BUSY_SHIFT)\
| BIT(IS_S_RX_EVENT_SHIFT) | BIT(IS_S_RD_EVENT_SHIFT)\
- | BIT(IS_S_TX_UNDERRUN_SHIFT))
+ | BIT(IS_S_TX_UNDERRUN_SHIFT) | BIT(IS_S_RX_FIFO_FULL_SHIFT)\
+ | BIT(IS_S_RX_THLD_SHIFT))
static int bcm_iproc_i2c_reg_slave(struct i2c_client *slave);
static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave);
@@ -259,6 +276,7 @@ static void bcm_iproc_i2c_slave_init(
{
u32 val;
+ iproc_i2c->tx_underrun = 0;
if (need_reset) {
/* put controller in reset */
val = iproc_i2c_rd_reg(iproc_i2c, CFG_OFFSET);
@@ -295,8 +313,13 @@ static void bcm_iproc_i2c_slave_init(
/* Enable interrupt register to indicate a valid byte in receive fifo */
val = BIT(IE_S_RX_EVENT_SHIFT);
+ /* Enable interrupt register to indicate Slave Rx FIFO Full */
+ val |= BIT(IE_S_RX_FIFO_FULL_SHIFT);
+ /* Enable interrupt register to indicate a Master read transaction */
+ val |= BIT(IE_S_RD_EVENT_SHIFT);
/* Enable interrupt register for the Slave BUSY command */
val |= BIT(IE_S_START_BUSY_SHIFT);
+ iproc_i2c->slave_int_mask = val;
iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val);
}
@@ -311,9 +334,10 @@ static void bcm_iproc_i2c_check_slave_status(
return;
val = (val >> S_CMD_STATUS_SHIFT) & S_CMD_STATUS_MASK;
- if (val == S_CMD_STATUS_TIMEOUT) {
- dev_err(iproc_i2c->device, "slave random stretch time timeout\n");
-
+ if (val == S_CMD_STATUS_TIMEOUT || val == S_CMD_STATUS_MASTER_ABORT) {
+ dev_err(iproc_i2c->device, (val == S_CMD_STATUS_TIMEOUT) ?
+ "slave random stretch time timeout\n" :
+ "Master aborted read transaction\n");
/* re-initialize i2c for recovery */
bcm_iproc_i2c_enable_disable(iproc_i2c, false);
bcm_iproc_i2c_slave_init(iproc_i2c, true);
@@ -321,76 +345,187 @@ static void bcm_iproc_i2c_check_slave_status(
}
}
-static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c,
- u32 status)
+static void bcm_iproc_i2c_slave_read(struct bcm_iproc_i2c_dev *iproc_i2c)
{
+ u8 rx_data, rx_status;
+ u32 rx_bytes = 0;
u32 val;
- u8 value, rx_status;
- /* Slave RX byte receive */
- if (status & BIT(IS_S_RX_EVENT_SHIFT)) {
+ while (rx_bytes < MAX_SLAVE_RX_PER_INT) {
val = iproc_i2c_rd_reg(iproc_i2c, S_RX_OFFSET);
rx_status = (val >> S_RX_STATUS_SHIFT) & S_RX_STATUS_MASK;
- if (rx_status == I2C_SLAVE_RX_START) {
- /* Start of SMBUS for Master write */
- i2c_slave_event(iproc_i2c->slave,
- I2C_SLAVE_WRITE_REQUESTED, &value);
+ rx_data = ((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK);
- val = iproc_i2c_rd_reg(iproc_i2c, S_RX_OFFSET);
- value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK);
+ if (rx_status == I2C_SLAVE_RX_START) {
+ /* Start of SMBUS Master write */
i2c_slave_event(iproc_i2c->slave,
- I2C_SLAVE_WRITE_RECEIVED, &value);
- } else if (status & BIT(IS_S_RD_EVENT_SHIFT)) {
- /* Start of SMBUS for Master Read */
+ I2C_SLAVE_WRITE_REQUESTED, &rx_data);
+ iproc_i2c->rx_start_rcvd = true;
+ iproc_i2c->slave_read_complete = false;
+ } else if (rx_status == I2C_SLAVE_RX_DATA &&
+ iproc_i2c->rx_start_rcvd) {
+ /* Middle of SMBUS Master write */
i2c_slave_event(iproc_i2c->slave,
- I2C_SLAVE_READ_REQUESTED, &value);
- iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, value);
+ I2C_SLAVE_WRITE_RECEIVED, &rx_data);
+ } else if (rx_status == I2C_SLAVE_RX_END &&
+ iproc_i2c->rx_start_rcvd) {
+ /* End of SMBUS Master write */
+ if (iproc_i2c->slave_rx_only)
+ i2c_slave_event(iproc_i2c->slave,
+ I2C_SLAVE_WRITE_RECEIVED,
+ &rx_data);
+
+ i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_STOP,
+ &rx_data);
+ } else if (rx_status == I2C_SLAVE_RX_FIFO_EMPTY) {
+ iproc_i2c->rx_start_rcvd = false;
+ iproc_i2c->slave_read_complete = true;
+ break;
+ }
- val = BIT(S_CMD_START_BUSY_SHIFT);
- iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val);
+ rx_bytes++;
+ }
+}
- /*
- * Enable interrupt for TX FIFO becomes empty and
- * less than PKT_LENGTH bytes were output on the SMBUS
- */
- val = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET);
- val |= BIT(IE_S_TX_UNDERRUN_SHIFT);
- iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val);
- } else {
- /* Master write other than start */
- value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK);
+static void slave_rx_tasklet_fn(unsigned long data)
+{
+ struct bcm_iproc_i2c_dev *iproc_i2c = (struct bcm_iproc_i2c_dev *)data;
+ u32 int_clr;
+
+ bcm_iproc_i2c_slave_read(iproc_i2c);
+
+ /* clear pending IS_S_RX_EVENT_SHIFT interrupt */
+ int_clr = BIT(IS_S_RX_EVENT_SHIFT);
+
+ if (!iproc_i2c->slave_rx_only && iproc_i2c->slave_read_complete) {
+ /*
+ * In case of single byte master-read request,
+ * IS_S_TX_UNDERRUN_SHIFT event is generated before
+ * IS_S_START_BUSY_SHIFT event. Hence start slave data send
+ * from first IS_S_TX_UNDERRUN_SHIFT event.
+ *
+ * This means don't send any data from slave when
+ * IS_S_RD_EVENT_SHIFT event is generated else it will increment
+ * eeprom or other backend slave driver read pointer twice.
+ */
+ iproc_i2c->tx_underrun = 0;
+ iproc_i2c->slave_int_mask |= BIT(IE_S_TX_UNDERRUN_SHIFT);
+
+ /* clear IS_S_RD_EVENT_SHIFT interrupt */
+ int_clr |= BIT(IS_S_RD_EVENT_SHIFT);
+ }
+
+ /* clear slave interrupt */
+ iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, int_clr);
+ /* enable slave interrupts */
+ iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, iproc_i2c->slave_int_mask);
+}
+
+static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c,
+ u32 status)
+{
+ u32 val;
+ u8 value;
+
+ /*
+ * Slave events in case of master-write, master-write-read and,
+ * master-read
+ *
+ * Master-write : only IS_S_RX_EVENT_SHIFT event
+ * Master-write-read: both IS_S_RX_EVENT_SHIFT and IS_S_RD_EVENT_SHIFT
+ * events
+ * Master-read : both IS_S_RX_EVENT_SHIFT and IS_S_RD_EVENT_SHIFT
+ * events or only IS_S_RD_EVENT_SHIFT
+ *
+ * iproc has a slave rx fifo size of 64 bytes. Rx fifo full interrupt
+ * (IS_S_RX_FIFO_FULL_SHIFT) will be generated when RX fifo becomes
+ * full. This can happen if Master issues write requests of more than
+ * 64 bytes.
+ */
+ if (status & BIT(IS_S_RX_EVENT_SHIFT) ||
+ status & BIT(IS_S_RD_EVENT_SHIFT) ||
+ status & BIT(IS_S_RX_FIFO_FULL_SHIFT)) {
+ /* disable slave interrupts */
+ val = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET);
+ val &= ~iproc_i2c->slave_int_mask;
+ iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val);
+
+ if (status & BIT(IS_S_RD_EVENT_SHIFT))
+ /* Master-write-read request */
+ iproc_i2c->slave_rx_only = false;
+ else
+ /* Master-write request only */
+ iproc_i2c->slave_rx_only = true;
+
+ /* schedule tasklet to read data later */
+ tasklet_schedule(&iproc_i2c->slave_rx_tasklet);
+
+ /*
+ * clear only IS_S_RX_EVENT_SHIFT and
+ * IS_S_RX_FIFO_FULL_SHIFT interrupt.
+ */
+ val = BIT(IS_S_RX_EVENT_SHIFT);
+ if (status & BIT(IS_S_RX_FIFO_FULL_SHIFT))
+ val |= BIT(IS_S_RX_FIFO_FULL_SHIFT);
+ iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, val);
+ }
+
+ if (status & BIT(IS_S_TX_UNDERRUN_SHIFT)) {
+ iproc_i2c->tx_underrun++;
+ if (iproc_i2c->tx_underrun == 1)
+ /* Start of SMBUS for Master Read */
i2c_slave_event(iproc_i2c->slave,
- I2C_SLAVE_WRITE_RECEIVED, &value);
- if (rx_status == I2C_SLAVE_RX_END)
- i2c_slave_event(iproc_i2c->slave,
- I2C_SLAVE_STOP, &value);
- }
- } else if (status & BIT(IS_S_TX_UNDERRUN_SHIFT)) {
- /* Master read other than start */
- i2c_slave_event(iproc_i2c->slave,
- I2C_SLAVE_READ_PROCESSED, &value);
+ I2C_SLAVE_READ_REQUESTED,
+ &value);
+ else
+ /* Master read other than start */
+ i2c_slave_event(iproc_i2c->slave,
+ I2C_SLAVE_READ_PROCESSED,
+ &value);
iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, value);
+ /* start transfer */
val = BIT(S_CMD_START_BUSY_SHIFT);
iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val);
+
+ /* clear interrupt */
+ iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET,
+ BIT(IS_S_TX_UNDERRUN_SHIFT));
}
- /* Stop */
+ /* Stop received from master in case of master read transaction */
if (status & BIT(IS_S_START_BUSY_SHIFT)) {
- i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_STOP, &value);
/*
- * Enable interrupt for TX FIFO becomes empty and
+ * Disable interrupt for TX FIFO becomes empty and
* less than PKT_LENGTH bytes were output on the SMBUS
*/
- val = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET);
- val &= ~BIT(IE_S_TX_UNDERRUN_SHIFT);
- iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val);
+ iproc_i2c->slave_int_mask &= ~BIT(IE_S_TX_UNDERRUN_SHIFT);
+ iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET,
+ iproc_i2c->slave_int_mask);
+
+ /* End of SMBUS for Master Read */
+ val = BIT(S_TX_WR_STATUS_SHIFT);
+ iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, val);
+
+ val = BIT(S_CMD_START_BUSY_SHIFT);
+ iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val);
+
+ /* flush TX FIFOs */
+ val = iproc_i2c_rd_reg(iproc_i2c, S_FIFO_CTRL_OFFSET);
+ val |= (BIT(S_FIFO_TX_FLUSH_SHIFT));
+ iproc_i2c_wr_reg(iproc_i2c, S_FIFO_CTRL_OFFSET, val);
+
+ i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_STOP, &value);
+
+ /* clear interrupt */
+ iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET,
+ BIT(IS_S_START_BUSY_SHIFT));
}
- /* clear interrupt status */
- iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, status);
+ /* check slave transmit status only if slave is transmitting */
+ if (!iproc_i2c->slave_rx_only)
+ bcm_iproc_i2c_check_slave_status(iproc_i2c);
- bcm_iproc_i2c_check_slave_status(iproc_i2c);
return true;
}
@@ -505,12 +640,17 @@ static void bcm_iproc_i2c_process_m_event(struct bcm_iproc_i2c_dev *iproc_i2c,
static irqreturn_t bcm_iproc_i2c_isr(int irq, void *data)
{
struct bcm_iproc_i2c_dev *iproc_i2c = data;
- u32 status = iproc_i2c_rd_reg(iproc_i2c, IS_OFFSET);
+ u32 slave_status;
+ u32 status;
bool ret;
- u32 sl_status = status & ISR_MASK_SLAVE;
- if (sl_status) {
- ret = bcm_iproc_i2c_slave_isr(iproc_i2c, sl_status);
+ status = iproc_i2c_rd_reg(iproc_i2c, IS_OFFSET);
+ /* process only slave interrupt which are enabled */
+ slave_status = status & iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET) &
+ ISR_MASK_SLAVE;
+
+ if (slave_status) {
+ ret = bcm_iproc_i2c_slave_isr(iproc_i2c, slave_status);
if (ret)
return IRQ_HANDLED;
else
@@ -1066,6 +1206,10 @@ static int bcm_iproc_i2c_reg_slave(struct i2c_client *slave)
return -EAFNOSUPPORT;
iproc_i2c->slave = slave;
+
+ tasklet_init(&iproc_i2c->slave_rx_tasklet, slave_rx_tasklet_fn,
+ (unsigned long)iproc_i2c);
+
bcm_iproc_i2c_slave_init(iproc_i2c, false);
return 0;
}
@@ -1086,6 +1230,8 @@ static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave)
IE_S_ALL_INTERRUPT_SHIFT);
iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, tmp);
+ tasklet_kill(&iproc_i2c->slave_rx_tasklet);
+
/* Erase the slave address programmed */
tmp = iproc_i2c_rd_reg(iproc_i2c, S_CFG_SMBUS_ADDR_OFFSET);
tmp &= ~BIT(S_CFG_EN_NIC_SMB_ADDR3_SHIFT);
diff --git a/drivers/i2c/busses/i2c-digicolor.c b/drivers/i2c/busses/i2c-digicolor.c
index f67639dc74b7..60c838c7c454 100644
--- a/drivers/i2c/busses/i2c-digicolor.c
+++ b/drivers/i2c/busses/i2c-digicolor.c
@@ -160,12 +160,11 @@ static irqreturn_t dc_i2c_irq(int irq, void *dev_id)
{
struct dc_i2c *i2c = dev_id;
int cmd_status = dc_i2c_cmd_status(i2c);
- unsigned long flags;
u8 addr_cmd;
writeb_relaxed(1, i2c->regs + II_INTFLAG_CLEAR);
- spin_lock_irqsave(&i2c->lock, flags);
+ spin_lock(&i2c->lock);
if (cmd_status == II_CMD_STATUS_ACK_BAD
|| cmd_status == II_CMD_STATUS_ABORT) {
@@ -207,7 +206,7 @@ static irqreturn_t dc_i2c_irq(int irq, void *dev_id)
}
out:
- spin_unlock_irqrestore(&i2c->lock, flags);
+ spin_unlock(&i2c->lock);
return IRQ_HANDLED;
}
diff --git a/drivers/i2c/busses/i2c-efm32.c b/drivers/i2c/busses/i2c-efm32.c
deleted file mode 100644
index f6e13ceeb2b3..000000000000
--- a/drivers/i2c/busses/i2c-efm32.c
+++ /dev/null
@@ -1,469 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2014 Uwe Kleine-Koenig for Pengutronix
- */
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-
-#define DRIVER_NAME "efm32-i2c"
-
-#define MASK_VAL(mask, val) ((val << __ffs(mask)) & mask)
-
-#define REG_CTRL 0x00
-#define REG_CTRL_EN 0x00001
-#define REG_CTRL_SLAVE 0x00002
-#define REG_CTRL_AUTOACK 0x00004
-#define REG_CTRL_AUTOSE 0x00008
-#define REG_CTRL_AUTOSN 0x00010
-#define REG_CTRL_ARBDIS 0x00020
-#define REG_CTRL_GCAMEN 0x00040
-#define REG_CTRL_CLHR__MASK 0x00300
-#define REG_CTRL_BITO__MASK 0x03000
-#define REG_CTRL_BITO_OFF 0x00000
-#define REG_CTRL_BITO_40PCC 0x01000
-#define REG_CTRL_BITO_80PCC 0x02000
-#define REG_CTRL_BITO_160PCC 0x03000
-#define REG_CTRL_GIBITO 0x08000
-#define REG_CTRL_CLTO__MASK 0x70000
-#define REG_CTRL_CLTO_OFF 0x00000
-
-#define REG_CMD 0x04
-#define REG_CMD_START 0x00001
-#define REG_CMD_STOP 0x00002
-#define REG_CMD_ACK 0x00004
-#define REG_CMD_NACK 0x00008
-#define REG_CMD_CONT 0x00010
-#define REG_CMD_ABORT 0x00020
-#define REG_CMD_CLEARTX 0x00040
-#define REG_CMD_CLEARPC 0x00080
-
-#define REG_STATE 0x08
-#define REG_STATE_BUSY 0x00001
-#define REG_STATE_MASTER 0x00002
-#define REG_STATE_TRANSMITTER 0x00004
-#define REG_STATE_NACKED 0x00008
-#define REG_STATE_BUSHOLD 0x00010
-#define REG_STATE_STATE__MASK 0x000e0
-#define REG_STATE_STATE_IDLE 0x00000
-#define REG_STATE_STATE_WAIT 0x00020
-#define REG_STATE_STATE_START 0x00040
-#define REG_STATE_STATE_ADDR 0x00060
-#define REG_STATE_STATE_ADDRACK 0x00080
-#define REG_STATE_STATE_DATA 0x000a0
-#define REG_STATE_STATE_DATAACK 0x000c0
-
-#define REG_STATUS 0x0c
-#define REG_STATUS_PSTART 0x00001
-#define REG_STATUS_PSTOP 0x00002
-#define REG_STATUS_PACK 0x00004
-#define REG_STATUS_PNACK 0x00008
-#define REG_STATUS_PCONT 0x00010
-#define REG_STATUS_PABORT 0x00020
-#define REG_STATUS_TXC 0x00040
-#define REG_STATUS_TXBL 0x00080
-#define REG_STATUS_RXDATAV 0x00100
-
-#define REG_CLKDIV 0x10
-#define REG_CLKDIV_DIV__MASK 0x001ff
-#define REG_CLKDIV_DIV(div) MASK_VAL(REG_CLKDIV_DIV__MASK, (div))
-
-#define REG_SADDR 0x14
-#define REG_SADDRMASK 0x18
-#define REG_RXDATA 0x1c
-#define REG_RXDATAP 0x20
-#define REG_TXDATA 0x24
-#define REG_IF 0x28
-#define REG_IF_START 0x00001
-#define REG_IF_RSTART 0x00002
-#define REG_IF_ADDR 0x00004
-#define REG_IF_TXC 0x00008
-#define REG_IF_TXBL 0x00010
-#define REG_IF_RXDATAV 0x00020
-#define REG_IF_ACK 0x00040
-#define REG_IF_NACK 0x00080
-#define REG_IF_MSTOP 0x00100
-#define REG_IF_ARBLOST 0x00200
-#define REG_IF_BUSERR 0x00400
-#define REG_IF_BUSHOLD 0x00800
-#define REG_IF_TXOF 0x01000
-#define REG_IF_RXUF 0x02000
-#define REG_IF_BITO 0x04000
-#define REG_IF_CLTO 0x08000
-#define REG_IF_SSTOP 0x10000
-
-#define REG_IFS 0x2c
-#define REG_IFC 0x30
-#define REG_IFC__MASK 0x1ffcf
-
-#define REG_IEN 0x34
-
-#define REG_ROUTE 0x38
-#define REG_ROUTE_SDAPEN 0x00001
-#define REG_ROUTE_SCLPEN 0x00002
-#define REG_ROUTE_LOCATION__MASK 0x00700
-#define REG_ROUTE_LOCATION(n) MASK_VAL(REG_ROUTE_LOCATION__MASK, (n))
-
-struct efm32_i2c_ddata {
- struct i2c_adapter adapter;
-
- struct clk *clk;
- void __iomem *base;
- unsigned int irq;
- u8 location;
- unsigned long frequency;
-
- /* transfer data */
- struct completion done;
- struct i2c_msg *msgs;
- size_t num_msgs;
- size_t current_word, current_msg;
- int retval;
-};
-
-static u32 efm32_i2c_read32(struct efm32_i2c_ddata *ddata, unsigned offset)
-{
- return readl(ddata->base + offset);
-}
-
-static void efm32_i2c_write32(struct efm32_i2c_ddata *ddata,
- unsigned offset, u32 value)
-{
- writel(value, ddata->base + offset);
-}
-
-static void efm32_i2c_send_next_msg(struct efm32_i2c_ddata *ddata)
-{
- struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg];
-
- efm32_i2c_write32(ddata, REG_CMD, REG_CMD_START);
- efm32_i2c_write32(ddata, REG_TXDATA, i2c_8bit_addr_from_msg(cur_msg));
-}
-
-static void efm32_i2c_send_next_byte(struct efm32_i2c_ddata *ddata)
-{
- struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg];
-
- if (ddata->current_word >= cur_msg->len) {
- /* cur_msg completely transferred */
- ddata->current_word = 0;
- ddata->current_msg += 1;
-
- if (ddata->current_msg >= ddata->num_msgs) {
- efm32_i2c_write32(ddata, REG_CMD, REG_CMD_STOP);
- complete(&ddata->done);
- } else {
- efm32_i2c_send_next_msg(ddata);
- }
- } else {
- efm32_i2c_write32(ddata, REG_TXDATA,
- cur_msg->buf[ddata->current_word++]);
- }
-}
-
-static void efm32_i2c_recv_next_byte(struct efm32_i2c_ddata *ddata)
-{
- struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg];
-
- cur_msg->buf[ddata->current_word] = efm32_i2c_read32(ddata, REG_RXDATA);
- ddata->current_word += 1;
- if (ddata->current_word >= cur_msg->len) {
- /* cur_msg completely transferred */
- ddata->current_word = 0;
- ddata->current_msg += 1;
-
- efm32_i2c_write32(ddata, REG_CMD, REG_CMD_NACK);
-
- if (ddata->current_msg >= ddata->num_msgs) {
- efm32_i2c_write32(ddata, REG_CMD, REG_CMD_STOP);
- complete(&ddata->done);
- } else {
- efm32_i2c_send_next_msg(ddata);
- }
- } else {
- efm32_i2c_write32(ddata, REG_CMD, REG_CMD_ACK);
- }
-}
-
-static irqreturn_t efm32_i2c_irq(int irq, void *dev_id)
-{
- struct efm32_i2c_ddata *ddata = dev_id;
- struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg];
- u32 irqflag = efm32_i2c_read32(ddata, REG_IF);
- u32 state = efm32_i2c_read32(ddata, REG_STATE);
-
- efm32_i2c_write32(ddata, REG_IFC, irqflag & REG_IFC__MASK);
-
- switch (state & REG_STATE_STATE__MASK) {
- case REG_STATE_STATE_IDLE:
- /* arbitration lost? */
- ddata->retval = -EAGAIN;
- complete(&ddata->done);
- break;
- case REG_STATE_STATE_WAIT:
- /*
- * huh, this shouldn't happen.
- * Reset hardware state and get out
- */
- ddata->retval = -EIO;
- efm32_i2c_write32(ddata, REG_CMD,
- REG_CMD_STOP | REG_CMD_ABORT |
- REG_CMD_CLEARTX | REG_CMD_CLEARPC);
- complete(&ddata->done);
- break;
- case REG_STATE_STATE_START:
- /* "caller" is expected to send an address */
- break;
- case REG_STATE_STATE_ADDR:
- /* wait for Ack or NAck of slave */
- break;
- case REG_STATE_STATE_ADDRACK:
- if (state & REG_STATE_NACKED) {
- efm32_i2c_write32(ddata, REG_CMD, REG_CMD_STOP);
- ddata->retval = -ENXIO;
- complete(&ddata->done);
- } else if (cur_msg->flags & I2C_M_RD) {
- /* wait for slave to send first data byte */
- } else {
- efm32_i2c_send_next_byte(ddata);
- }
- break;
- case REG_STATE_STATE_DATA:
- if (cur_msg->flags & I2C_M_RD) {
- efm32_i2c_recv_next_byte(ddata);
- } else {
- /* wait for Ack or Nack of slave */
- }
- break;
- case REG_STATE_STATE_DATAACK:
- if (state & REG_STATE_NACKED) {
- efm32_i2c_write32(ddata, REG_CMD, REG_CMD_STOP);
- complete(&ddata->done);
- } else {
- efm32_i2c_send_next_byte(ddata);
- }
- }
-
- return IRQ_HANDLED;
-}
-
-static int efm32_i2c_master_xfer(struct i2c_adapter *adap,
- struct i2c_msg *msgs, int num)
-{
- struct efm32_i2c_ddata *ddata = i2c_get_adapdata(adap);
- int ret;
-
- if (ddata->msgs)
- return -EBUSY;
-
- ddata->msgs = msgs;
- ddata->num_msgs = num;
- ddata->current_word = 0;
- ddata->current_msg = 0;
- ddata->retval = -EIO;
-
- reinit_completion(&ddata->done);
-
- dev_dbg(&ddata->adapter.dev, "state: %08x, status: %08x\n",
- efm32_i2c_read32(ddata, REG_STATE),
- efm32_i2c_read32(ddata, REG_STATUS));
-
- efm32_i2c_send_next_msg(ddata);
-
- wait_for_completion(&ddata->done);
-
- if (ddata->current_msg >= ddata->num_msgs)
- ret = ddata->num_msgs;
- else
- ret = ddata->retval;
-
- return ret;
-}
-
-static u32 efm32_i2c_functionality(struct i2c_adapter *adap)
-{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-}
-
-static const struct i2c_algorithm efm32_i2c_algo = {
- .master_xfer = efm32_i2c_master_xfer,
- .functionality = efm32_i2c_functionality,
-};
-
-static u32 efm32_i2c_get_configured_location(struct efm32_i2c_ddata *ddata)
-{
- u32 reg = efm32_i2c_read32(ddata, REG_ROUTE);
-
- return (reg & REG_ROUTE_LOCATION__MASK) >>
- __ffs(REG_ROUTE_LOCATION__MASK);
-}
-
-static int efm32_i2c_probe(struct platform_device *pdev)
-{
- struct efm32_i2c_ddata *ddata;
- struct resource *res;
- unsigned long rate;
- struct device_node *np = pdev->dev.of_node;
- u32 location, frequency;
- int ret;
- u32 clkdiv;
-
- ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
- if (!ddata)
- return -ENOMEM;
- platform_set_drvdata(pdev, ddata);
-
- init_completion(&ddata->done);
- strlcpy(ddata->adapter.name, pdev->name, sizeof(ddata->adapter.name));
- ddata->adapter.owner = THIS_MODULE;
- ddata->adapter.algo = &efm32_i2c_algo;
- ddata->adapter.dev.parent = &pdev->dev;
- ddata->adapter.dev.of_node = pdev->dev.of_node;
- i2c_set_adapdata(&ddata->adapter, ddata);
-
- ddata->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(ddata->clk)) {
- ret = PTR_ERR(ddata->clk);
- dev_err(&pdev->dev, "failed to get clock: %d\n", ret);
- return ret;
- }
-
- ddata->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
- if (IS_ERR(ddata->base))
- return PTR_ERR(ddata->base);
-
- if (resource_size(res) < 0x42) {
- dev_err(&pdev->dev, "memory resource too small\n");
- return -EINVAL;
- }
-
- ret = platform_get_irq(pdev, 0);
- if (ret <= 0) {
- if (!ret)
- ret = -EINVAL;
- return ret;
- }
-
- ddata->irq = ret;
-
- ret = clk_prepare_enable(ddata->clk);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to enable clock (%d)\n", ret);
- return ret;
- }
-
-
- ret = of_property_read_u32(np, "energymicro,location", &location);
-
- if (ret)
- /* fall back to wrongly namespaced property */
- ret = of_property_read_u32(np, "efm32,location", &location);
-
- if (!ret) {
- dev_dbg(&pdev->dev, "using location %u\n", location);
- } else {
- /* default to location configured in hardware */
- location = efm32_i2c_get_configured_location(ddata);
-
- dev_info(&pdev->dev, "fall back to location %u\n", location);
- }
-
- ddata->location = location;
-
- ret = of_property_read_u32(np, "clock-frequency", &frequency);
- if (!ret) {
- dev_dbg(&pdev->dev, "using frequency %u\n", frequency);
- } else {
- frequency = I2C_MAX_STANDARD_MODE_FREQ;
- dev_info(&pdev->dev, "defaulting to 100 kHz\n");
- }
- ddata->frequency = frequency;
-
- rate = clk_get_rate(ddata->clk);
- if (!rate) {
- dev_err(&pdev->dev, "there is no input clock available\n");
- ret = -EINVAL;
- goto err_disable_clk;
- }
- clkdiv = DIV_ROUND_UP(rate, 8 * ddata->frequency) - 1;
- if (clkdiv >= 0x200) {
- dev_err(&pdev->dev,
- "input clock too fast (%lu) to divide down to bus freq (%lu)",
- rate, ddata->frequency);
- ret = -EINVAL;
- goto err_disable_clk;
- }
-
- dev_dbg(&pdev->dev, "input clock = %lu, bus freq = %lu, clkdiv = %lu\n",
- rate, ddata->frequency, (unsigned long)clkdiv);
- efm32_i2c_write32(ddata, REG_CLKDIV, REG_CLKDIV_DIV(clkdiv));
-
- efm32_i2c_write32(ddata, REG_ROUTE, REG_ROUTE_SDAPEN |
- REG_ROUTE_SCLPEN |
- REG_ROUTE_LOCATION(ddata->location));
-
- efm32_i2c_write32(ddata, REG_CTRL, REG_CTRL_EN |
- REG_CTRL_BITO_160PCC | 0 * REG_CTRL_GIBITO);
-
- efm32_i2c_write32(ddata, REG_IFC, REG_IFC__MASK);
- efm32_i2c_write32(ddata, REG_IEN, REG_IF_TXC | REG_IF_ACK | REG_IF_NACK
- | REG_IF_ARBLOST | REG_IF_BUSERR | REG_IF_RXDATAV);
-
- /* to make bus idle */
- efm32_i2c_write32(ddata, REG_CMD, REG_CMD_ABORT);
-
- ret = request_irq(ddata->irq, efm32_i2c_irq, 0, DRIVER_NAME, ddata);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to request irq (%d)\n", ret);
- goto err_disable_clk;
- }
-
- ret = i2c_add_adapter(&ddata->adapter);
- if (ret) {
- free_irq(ddata->irq, ddata);
-
-err_disable_clk:
- clk_disable_unprepare(ddata->clk);
- }
- return ret;
-}
-
-static int efm32_i2c_remove(struct platform_device *pdev)
-{
- struct efm32_i2c_ddata *ddata = platform_get_drvdata(pdev);
-
- i2c_del_adapter(&ddata->adapter);
- free_irq(ddata->irq, ddata);
- clk_disable_unprepare(ddata->clk);
-
- return 0;
-}
-
-static const struct of_device_id efm32_i2c_dt_ids[] = {
- {
- .compatible = "energymicro,efm32-i2c",
- }, {
- /* sentinel */
- }
-};
-MODULE_DEVICE_TABLE(of, efm32_i2c_dt_ids);
-
-static struct platform_driver efm32_i2c_driver = {
- .probe = efm32_i2c_probe,
- .remove = efm32_i2c_remove,
-
- .driver = {
- .name = DRIVER_NAME,
- .of_match_table = efm32_i2c_dt_ids,
- },
-};
-module_platform_driver(efm32_i2c_driver);
-
-MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>");
-MODULE_DESCRIPTION("EFM32 i2c driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index b72a3c3ef2ab..b0f50dce9d0f 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -49,7 +49,7 @@ static int mmapped;
static wait_queue_head_t pcf_wait;
static int pcf_pending;
-static spinlock_t lock;
+static DEFINE_SPINLOCK(lock);
static struct i2c_adapter pcf_isa_ops;
@@ -132,7 +132,6 @@ static irqreturn_t pcf_isa_handler(int this_irq, void *dev_id) {
static int pcf_isa_init(void)
{
- spin_lock_init(&lock);
if (!mmapped) {
if (!request_region(base, 2, pcf_isa_ops.name)) {
printk(KERN_ERR "%s: requested I/O region (%#x:2) is "
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index a4a6825c8758..7a048abbf92b 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -520,5 +520,5 @@ module_exit(i2c_gpio_exit);
MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:i2c-gpio");
diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c
index ab15b1ec2ab3..c45f226c2b85 100644
--- a/drivers/i2c/busses/i2c-hix5hd2.c
+++ b/drivers/i2c/busses/i2c-hix5hd2.c
@@ -413,10 +413,8 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev)
return PTR_ERR(priv->regs);
irq = platform_get_irq(pdev, 0);
- if (irq <= 0) {
- dev_err(&pdev->dev, "cannot find HS-I2C IRQ\n");
+ if (irq <= 0)
return irq;
- }
priv->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(priv->clk)) {
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 877fe3733a42..4acee6f9e5a3 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -72,6 +72,7 @@
* Jasper Lake (SOC) 0x4da3 32 hard yes yes yes
* Comet Lake-V (PCH) 0xa3a3 32 hard yes yes yes
* Alder Lake-S (PCH) 0x7aa3 32 hard yes yes yes
+ * Alder Lake-P (PCH) 0x51a3 32 hard yes yes yes
*
* Features supported by this driver:
* Software PEC no
@@ -228,6 +229,7 @@
#define PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS 0x43a3
#define PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS 0x4b23
#define PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS 0x4da3
+#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS 0x51a3
#define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4
#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS 0x7aa3
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22
@@ -1084,6 +1086,7 @@ static const struct pci_device_id i801_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS) },
{ 0, }
};
@@ -1433,7 +1436,7 @@ static int i801_add_mux(struct i801_priv *priv)
const struct i801_mux_config *mux_config;
struct i2c_mux_gpio_platform_data gpio_data;
struct gpiod_lookup_table *lookup;
- int err, i;
+ int i;
if (!priv->mux_drvdata)
return 0;
@@ -1473,22 +1476,17 @@ static int i801_add_mux(struct i801_priv *priv)
PLATFORM_DEVID_NONE, &gpio_data,
sizeof(struct i2c_mux_gpio_platform_data));
if (IS_ERR(priv->mux_pdev)) {
- err = PTR_ERR(priv->mux_pdev);
gpiod_remove_lookup_table(lookup);
- priv->mux_pdev = NULL;
dev_err(dev, "Failed to register i2c-mux-gpio device\n");
- return err;
}
- return 0;
+ return PTR_ERR_OR_ZERO(priv->mux_pdev);
}
static void i801_del_mux(struct i801_priv *priv)
{
- if (priv->mux_pdev)
- platform_device_unregister(priv->mux_pdev);
- if (priv->lookup)
- gpiod_remove_lookup_table(priv->lookup);
+ platform_device_unregister(priv->mux_pdev);
+ gpiod_remove_lookup_table(priv->lookup);
}
static unsigned int i801_get_adapter_class(struct i801_priv *priv)
@@ -1772,6 +1770,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
case PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS:
case PCI_DEVICE_ID_INTEL_EBG_SMBUS:
case PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS:
+ case PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS:
priv->features |= FEATURE_BLOCK_PROC;
priv->features |= FEATURE_I2C_BLOCK_READ;
priv->features |= FEATURE_IRQ;
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index a8e8af57e33f..b80fdc1f0092 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -209,6 +209,7 @@ struct imx_i2c_struct {
struct imx_i2c_dma *dma;
struct i2c_client *slave;
+ enum i2c_slave_event last_slave_event;
};
static const struct imx_i2c_hwdata imx1_i2c_hwdata = {
@@ -550,7 +551,7 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
i2c_imx->cur_clk = i2c_clk_rate;
- div = (i2c_clk_rate + i2c_imx->bitrate - 1) / i2c_imx->bitrate;
+ div = DIV_ROUND_UP(i2c_clk_rate, i2c_imx->bitrate);
if (div < i2c_clk_div[0].div)
i = 0;
else if (div > i2c_clk_div[i2c_imx->hwdata->ndivs - 1].div)
@@ -568,8 +569,8 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
* This delay is used in I2C bus disable function
* to fix chip hardware bug.
*/
- i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div
- + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2);
+ i2c_imx->disable_delay = DIV_ROUND_UP(500000U * i2c_clk_div[i].div,
+ i2c_clk_rate / 2);
#ifdef CONFIG_I2C_DEBUG_BUS
dev_dbg(&i2c_imx->adapter.dev, "I2C_CLK=%d, REQ DIV=%d\n",
@@ -675,6 +676,36 @@ static void i2c_imx_enable_bus_idle(struct imx_i2c_struct *i2c_imx)
}
}
+static void i2c_imx_slave_event(struct imx_i2c_struct *i2c_imx,
+ enum i2c_slave_event event, u8 *val)
+{
+ i2c_slave_event(i2c_imx->slave, event, val);
+ i2c_imx->last_slave_event = event;
+}
+
+static void i2c_imx_slave_finish_op(struct imx_i2c_struct *i2c_imx)
+{
+ u8 val;
+
+ while (i2c_imx->last_slave_event != I2C_SLAVE_STOP) {
+ switch (i2c_imx->last_slave_event) {
+ case I2C_SLAVE_READ_REQUESTED:
+ i2c_imx_slave_event(i2c_imx, I2C_SLAVE_READ_PROCESSED,
+ &val);
+ break;
+
+ case I2C_SLAVE_WRITE_REQUESTED:
+ case I2C_SLAVE_READ_PROCESSED:
+ case I2C_SLAVE_WRITE_RECEIVED:
+ i2c_imx_slave_event(i2c_imx, I2C_SLAVE_STOP, &val);
+ break;
+
+ case I2C_SLAVE_STOP:
+ break;
+ }
+ }
+}
+
static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx,
unsigned int status, unsigned int ctl)
{
@@ -687,9 +718,11 @@ static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx,
}
if (status & I2SR_IAAS) { /* Addressed as a slave */
+ i2c_imx_slave_finish_op(i2c_imx);
if (status & I2SR_SRW) { /* Master wants to read from us*/
dev_dbg(&i2c_imx->adapter.dev, "read requested");
- i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value);
+ i2c_imx_slave_event(i2c_imx,
+ I2C_SLAVE_READ_REQUESTED, &value);
/* Slave transmit */
ctl |= I2CR_MTX;
@@ -699,7 +732,8 @@ static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx,
imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
} else { /* Master wants to write to us */
dev_dbg(&i2c_imx->adapter.dev, "write requested");
- i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_REQUESTED, &value);
+ i2c_imx_slave_event(i2c_imx,
+ I2C_SLAVE_WRITE_REQUESTED, &value);
/* Slave receive */
ctl &= ~I2CR_MTX;
@@ -710,17 +744,20 @@ static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx,
} else if (!(ctl & I2CR_MTX)) { /* Receive mode */
if (status & I2SR_IBB) { /* No STOP signal detected */
value = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
- i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_RECEIVED, &value);
+ i2c_imx_slave_event(i2c_imx,
+ I2C_SLAVE_WRITE_RECEIVED, &value);
} else { /* STOP signal is detected */
dev_dbg(&i2c_imx->adapter.dev,
"STOP signal detected");
- i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &value);
+ i2c_imx_slave_event(i2c_imx,
+ I2C_SLAVE_STOP, &value);
}
} else if (!(status & I2SR_RXAK)) { /* Transmit mode received ACK */
ctl |= I2CR_MTX;
imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
- i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_PROCESSED, &value);
+ i2c_imx_slave_event(i2c_imx,
+ I2C_SLAVE_READ_PROCESSED, &value);
imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR);
} else { /* Transmit mode received NAK */
@@ -761,6 +798,7 @@ static int i2c_imx_reg_slave(struct i2c_client *client)
return -EBUSY;
i2c_imx->slave = client;
+ i2c_imx->last_slave_event = I2C_SLAVE_STOP;
/* Resume */
ret = pm_runtime_get_sync(i2c_imx->adapter.dev.parent);
@@ -813,10 +851,17 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+
if (status & I2SR_IIF) {
i2c_imx_clear_irq(i2c_imx, I2SR_IIF);
- if (i2c_imx->slave && !(ctl & I2CR_MSTA))
- return i2c_imx_slave_isr(i2c_imx, status, ctl);
+ if (i2c_imx->slave) {
+ if (!(ctl & I2CR_MSTA)) {
+ return i2c_imx_slave_isr(i2c_imx, status, ctl);
+ } else if (i2c_imx->last_slave_event !=
+ I2C_SLAVE_STOP) {
+ i2c_imx_slave_finish_op(i2c_imx);
+ }
+ }
return i2c_imx_master_isr(i2c_imx, status);
}
diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c
index cb4a25ebb890..8509c5f11356 100644
--- a/drivers/i2c/busses/i2c-jz4780.c
+++ b/drivers/i2c/busses/i2c-jz4780.c
@@ -437,9 +437,8 @@ static irqreturn_t jz4780_i2c_irq(int irqno, void *dev_id)
unsigned short intst;
unsigned short intmsk;
struct jz4780_i2c *i2c = dev_id;
- unsigned long flags;
- spin_lock_irqsave(&i2c->lock, flags);
+ spin_lock(&i2c->lock);
intmsk = jz4780_i2c_readw(i2c, JZ4780_I2C_INTM);
intst = jz4780_i2c_readw(i2c, JZ4780_I2C_INTST);
@@ -551,7 +550,7 @@ static irqreturn_t jz4780_i2c_irq(int irqno, void *dev_id)
}
done:
- spin_unlock_irqrestore(&i2c->lock, flags);
+ spin_unlock(&i2c->lock);
return IRQ_HANDLED;
}
diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c
index 71d7bae2cbca..4e0b7c2882ce 100644
--- a/drivers/i2c/busses/i2c-mlxcpld.c
+++ b/drivers/i2c/busses/i2c-mlxcpld.c
@@ -1,34 +1,8 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
/*
- * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2016 Michael Shych <michaels@mellanox.com>
+ * Mellanox i2c driver
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the names of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * Copyright (C) 2016-2020 Mellanox Technologies
*/
#include <linux/delay.h>
@@ -37,7 +11,9 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/platform_data/mlxreg.h>
#include <linux/platform_device.h>
+#include <linux/regmap.h>
/* General defines */
#define MLXPLAT_CPLD_LPC_I2C_BASE_ADDR 0x2000
@@ -51,7 +27,7 @@
#define MLXCPLD_I2C_MAX_ADDR_LEN 4
#define MLXCPLD_I2C_RETR_NUM 2
#define MLXCPLD_I2C_XFER_TO 500000 /* usec */
-#define MLXCPLD_I2C_POLL_TIME 2000 /* usec */
+#define MLXCPLD_I2C_POLL_TIME 400 /* usec */
/* LPC I2C registers */
#define MLXCPLD_LPCI2C_CPBLTY_REG 0x0
@@ -72,6 +48,16 @@
#define MLXCPLD_LPCI2C_ACK_IND 1
#define MLXCPLD_LPCI2C_NACK_IND 2
+#define MLXCPLD_I2C_FREQ_1000KHZ_SET 0x04
+#define MLXCPLD_I2C_FREQ_400KHZ_SET 0x0f
+#define MLXCPLD_I2C_FREQ_100KHZ_SET 0x42
+
+enum mlxcpld_i2c_frequency {
+ MLXCPLD_I2C_FREQ_1000KHZ = 1,
+ MLXCPLD_I2C_FREQ_400KHZ = 2,
+ MLXCPLD_I2C_FREQ_100KHZ = 3,
+};
+
struct mlxcpld_i2c_curr_xfer {
u8 cmd;
u8 addr_width;
@@ -489,8 +475,45 @@ static struct i2c_adapter mlxcpld_i2c_adapter = {
.nr = MLXCPLD_I2C_BUS_NUM,
};
+static int
+mlxcpld_i2c_set_frequency(struct mlxcpld_i2c_priv *priv,
+ struct mlxreg_core_hotplug_platform_data *pdata)
+{
+ struct mlxreg_core_item *item = pdata->items;
+ struct mlxreg_core_data *data;
+ u32 regval;
+ u8 freq;
+ int err;
+
+ if (!item)
+ return 0;
+
+ /* Read frequency setting. */
+ data = item->data;
+ err = regmap_read(pdata->regmap, data->reg, &regval);
+ if (err)
+ return err;
+
+ /* Set frequency only if it is not 100KHz, which is default. */
+ switch ((data->reg & data->mask) >> data->bit) {
+ case MLXCPLD_I2C_FREQ_1000KHZ:
+ freq = MLXCPLD_I2C_FREQ_1000KHZ_SET;
+ break;
+ case MLXCPLD_I2C_FREQ_400KHZ:
+ freq = MLXCPLD_I2C_FREQ_400KHZ_SET;
+ break;
+ default:
+ return 0;
+ }
+
+ mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_HALF_CYC_REG, &freq, 1);
+
+ return 0;
+}
+
static int mlxcpld_i2c_probe(struct platform_device *pdev)
{
+ struct mlxreg_core_hotplug_platform_data *pdata;
struct mlxcpld_i2c_priv *priv;
int err;
u8 val;
@@ -505,6 +528,14 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev)
priv->dev = &pdev->dev;
priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR;
+ /* Set I2C bus frequency if platform data provides this info. */
+ pdata = dev_get_platdata(&pdev->dev);
+ if (pdata) {
+ err = mlxcpld_i2c_set_frequency(priv, pdata);
+ if (err)
+ goto mlxcpld_i2_probe_failed;
+ }
+
/* Register with i2c layer */
mlxcpld_i2c_adapter.timeout = usecs_to_jiffies(MLXCPLD_I2C_XFER_TO);
/* Read capability register */
@@ -523,8 +554,12 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev)
err = i2c_add_numbered_adapter(&priv->adap);
if (err)
- mutex_destroy(&priv->lock);
+ goto mlxcpld_i2_probe_failed;
+ return 0;
+
+mlxcpld_i2_probe_failed:
+ mutex_destroy(&priv->lock);
return err;
}
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 5cfe70aedced..c590d36b5fd1 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -18,6 +18,7 @@
#include <linux/mv643xx_i2c.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/consumer.h>
+#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/io.h>
#include <linux/of.h>
@@ -717,6 +718,10 @@ mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap);
int rc, ret = num;
+ rc = pm_runtime_resume_and_get(&adap->dev);
+ if (rc)
+ return rc;
+
BUG_ON(drv_data->msgs != NULL);
drv_data->msgs = msgs;
drv_data->num_msgs = num;
@@ -732,6 +737,9 @@ mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
drv_data->num_msgs = 0;
drv_data->msgs = NULL;
+ pm_runtime_mark_last_busy(&adap->dev);
+ pm_runtime_put_autosuspend(&adap->dev);
+
return ret;
}
@@ -805,7 +813,7 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
* need to know tclk in order to calculate bus clock
* factors.
*/
- if (IS_ERR(drv_data->clk)) {
+ if (!drv_data->clk) {
rc = -ENODEV;
goto out;
}
@@ -828,7 +836,6 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
rc = PTR_ERR(drv_data->rstc);
goto out;
}
- reset_control_deassert(drv_data->rstc);
/* Its not yet defined how timeouts will be specified in device tree.
* So hard code the value to 1 second.
@@ -894,6 +901,32 @@ static int mv64xxx_i2c_init_recovery_info(struct mv64xxx_i2c_data *drv_data,
}
static int
+mv64xxx_i2c_runtime_suspend(struct device *dev)
+{
+ struct mv64xxx_i2c_data *drv_data = dev_get_drvdata(dev);
+
+ reset_control_assert(drv_data->rstc);
+ clk_disable_unprepare(drv_data->reg_clk);
+ clk_disable_unprepare(drv_data->clk);
+
+ return 0;
+}
+
+static int
+mv64xxx_i2c_runtime_resume(struct device *dev)
+{
+ struct mv64xxx_i2c_data *drv_data = dev_get_drvdata(dev);
+
+ clk_prepare_enable(drv_data->clk);
+ clk_prepare_enable(drv_data->reg_clk);
+ reset_control_reset(drv_data->rstc);
+
+ mv64xxx_i2c_hw_init(drv_data);
+
+ return 0;
+}
+
+static int
mv64xxx_i2c_probe(struct platform_device *pd)
{
struct mv64xxx_i2c_data *drv_data;
@@ -920,18 +953,22 @@ mv64xxx_i2c_probe(struct platform_device *pd)
/* Not all platforms have clocks */
drv_data->clk = devm_clk_get(&pd->dev, NULL);
- if (PTR_ERR(drv_data->clk) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- if (!IS_ERR(drv_data->clk))
- clk_prepare_enable(drv_data->clk);
+ if (IS_ERR(drv_data->clk)) {
+ if (PTR_ERR(drv_data->clk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ drv_data->clk = NULL;
+ }
drv_data->reg_clk = devm_clk_get(&pd->dev, "reg");
- if (PTR_ERR(drv_data->reg_clk) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- if (!IS_ERR(drv_data->reg_clk))
- clk_prepare_enable(drv_data->reg_clk);
+ if (IS_ERR(drv_data->reg_clk)) {
+ if (PTR_ERR(drv_data->reg_clk) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ drv_data->reg_clk = NULL;
+ }
drv_data->irq = platform_get_irq(pd, 0);
+ if (drv_data->irq < 0)
+ return drv_data->irq;
if (pdata) {
drv_data->freq_m = pdata->freq_m;
@@ -942,16 +979,12 @@ mv64xxx_i2c_probe(struct platform_device *pd)
} else if (pd->dev.of_node) {
rc = mv64xxx_of_config(drv_data, &pd->dev);
if (rc)
- goto exit_clk;
- }
- if (drv_data->irq < 0) {
- rc = drv_data->irq;
- goto exit_reset;
+ return rc;
}
rc = mv64xxx_i2c_init_recovery_info(drv_data, &pd->dev);
if (rc == -EPROBE_DEFER)
- goto exit_reset;
+ return rc;
drv_data->adapter.dev.parent = &pd->dev;
drv_data->adapter.algo = &mv64xxx_i2c_algo;
@@ -962,7 +995,14 @@ mv64xxx_i2c_probe(struct platform_device *pd)
platform_set_drvdata(pd, drv_data);
i2c_set_adapdata(&drv_data->adapter, drv_data);
- mv64xxx_i2c_hw_init(drv_data);
+ pm_runtime_set_autosuspend_delay(&pd->dev, MSEC_PER_SEC);
+ pm_runtime_use_autosuspend(&pd->dev);
+ pm_runtime_enable(&pd->dev);
+ if (!pm_runtime_enabled(&pd->dev)) {
+ rc = mv64xxx_i2c_runtime_resume(&pd->dev);
+ if (rc)
+ goto exit_disable_pm;
+ }
rc = request_irq(drv_data->irq, mv64xxx_i2c_intr, 0,
MV64XXX_I2C_CTLR_NAME, drv_data);
@@ -970,7 +1010,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
dev_err(&drv_data->adapter.dev,
"mv64xxx: Can't register intr handler irq%d: %d\n",
drv_data->irq, rc);
- goto exit_reset;
+ goto exit_disable_pm;
} else if ((rc = i2c_add_numbered_adapter(&drv_data->adapter)) != 0) {
dev_err(&drv_data->adapter.dev,
"mv64xxx: Can't add i2c adapter, rc: %d\n", -rc);
@@ -981,54 +1021,50 @@ mv64xxx_i2c_probe(struct platform_device *pd)
exit_free_irq:
free_irq(drv_data->irq, drv_data);
-exit_reset:
- reset_control_assert(drv_data->rstc);
-exit_clk:
- clk_disable_unprepare(drv_data->reg_clk);
- clk_disable_unprepare(drv_data->clk);
+exit_disable_pm:
+ pm_runtime_disable(&pd->dev);
+ if (!pm_runtime_status_suspended(&pd->dev))
+ mv64xxx_i2c_runtime_suspend(&pd->dev);
return rc;
}
static int
-mv64xxx_i2c_remove(struct platform_device *dev)
+mv64xxx_i2c_remove(struct platform_device *pd)
{
- struct mv64xxx_i2c_data *drv_data = platform_get_drvdata(dev);
+ struct mv64xxx_i2c_data *drv_data = platform_get_drvdata(pd);
i2c_del_adapter(&drv_data->adapter);
free_irq(drv_data->irq, drv_data);
- reset_control_assert(drv_data->rstc);
- clk_disable_unprepare(drv_data->reg_clk);
- clk_disable_unprepare(drv_data->clk);
+ pm_runtime_disable(&pd->dev);
+ if (!pm_runtime_status_suspended(&pd->dev))
+ mv64xxx_i2c_runtime_suspend(&pd->dev);
return 0;
}
-#ifdef CONFIG_PM
-static int mv64xxx_i2c_resume(struct device *dev)
+static void
+mv64xxx_i2c_shutdown(struct platform_device *pd)
{
- struct mv64xxx_i2c_data *drv_data = dev_get_drvdata(dev);
-
- mv64xxx_i2c_hw_init(drv_data);
-
- return 0;
+ pm_runtime_disable(&pd->dev);
+ if (!pm_runtime_status_suspended(&pd->dev))
+ mv64xxx_i2c_runtime_suspend(&pd->dev);
}
-static const struct dev_pm_ops mv64xxx_i2c_pm = {
- .resume = mv64xxx_i2c_resume,
+static const struct dev_pm_ops mv64xxx_i2c_pm_ops = {
+ SET_RUNTIME_PM_OPS(mv64xxx_i2c_runtime_suspend,
+ mv64xxx_i2c_runtime_resume, NULL)
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
};
-#define mv64xxx_i2c_pm_ops (&mv64xxx_i2c_pm)
-#else
-#define mv64xxx_i2c_pm_ops NULL
-#endif
-
static struct platform_driver mv64xxx_i2c_driver = {
.probe = mv64xxx_i2c_probe,
.remove = mv64xxx_i2c_remove,
+ .shutdown = mv64xxx_i2c_shutdown,
.driver = {
.name = MV64XXX_I2C_CTLR_NAME,
- .pm = mv64xxx_i2c_pm_ops,
+ .pm = &mv64xxx_i2c_pm_ops,
.of_match_table = mv64xxx_i2c_of_match_table,
},
};
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index 046d241183c5..c3f584795911 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -86,6 +86,9 @@ struct geni_i2c_dev {
u32 clk_freq_out;
const struct geni_i2c_clk_fld *clk_fld;
int suspended;
+ void *dma_buf;
+ size_t xfer_len;
+ dma_addr_t dma_addr;
};
struct geni_i2c_err_log {
@@ -348,14 +351,65 @@ static void geni_i2c_tx_fsm_rst(struct geni_i2c_dev *gi2c)
dev_err(gi2c->se.dev, "Timeout resetting TX_FSM\n");
}
+static void geni_i2c_rx_msg_cleanup(struct geni_i2c_dev *gi2c,
+ struct i2c_msg *cur)
+{
+ gi2c->cur_rd = 0;
+ if (gi2c->dma_buf) {
+ if (gi2c->err)
+ geni_i2c_rx_fsm_rst(gi2c);
+ geni_se_rx_dma_unprep(&gi2c->se, gi2c->dma_addr, gi2c->xfer_len);
+ i2c_put_dma_safe_msg_buf(gi2c->dma_buf, cur, !gi2c->err);
+ }
+}
+
+static void geni_i2c_tx_msg_cleanup(struct geni_i2c_dev *gi2c,
+ struct i2c_msg *cur)
+{
+ gi2c->cur_wr = 0;
+ if (gi2c->dma_buf) {
+ if (gi2c->err)
+ geni_i2c_tx_fsm_rst(gi2c);
+ geni_se_tx_dma_unprep(&gi2c->se, gi2c->dma_addr, gi2c->xfer_len);
+ i2c_put_dma_safe_msg_buf(gi2c->dma_buf, cur, !gi2c->err);
+ }
+}
+
+static void geni_i2c_stop_xfer(struct geni_i2c_dev *gi2c)
+{
+ int ret;
+ u32 geni_status;
+ struct i2c_msg *cur;
+
+ /* Resume device, as runtime suspend can happen anytime during transfer */
+ ret = pm_runtime_get_sync(gi2c->se.dev);
+ if (ret < 0) {
+ dev_err(gi2c->se.dev, "Failed to resume device: %d\n", ret);
+ return;
+ }
+
+ geni_status = readl_relaxed(gi2c->se.base + SE_GENI_STATUS);
+ if (geni_status & M_GENI_CMD_ACTIVE) {
+ cur = gi2c->cur;
+ geni_i2c_abort_xfer(gi2c);
+ if (cur->flags & I2C_M_RD)
+ geni_i2c_rx_msg_cleanup(gi2c, cur);
+ else
+ geni_i2c_tx_msg_cleanup(gi2c, cur);
+ }
+
+ pm_runtime_put_sync_suspend(gi2c->se.dev);
+}
+
static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
u32 m_param)
{
- dma_addr_t rx_dma;
+ dma_addr_t rx_dma = 0;
unsigned long time_left;
void *dma_buf;
struct geni_se *se = &gi2c->se;
size_t len = msg->len;
+ struct i2c_msg *cur;
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);
if (dma_buf)
@@ -370,19 +424,18 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
geni_se_select_mode(se, GENI_SE_FIFO);
i2c_put_dma_safe_msg_buf(dma_buf, msg, false);
dma_buf = NULL;
+ } else {
+ gi2c->xfer_len = len;
+ gi2c->dma_addr = rx_dma;
+ gi2c->dma_buf = dma_buf;
}
+ cur = gi2c->cur;
time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT);
if (!time_left)
geni_i2c_abort_xfer(gi2c);
- gi2c->cur_rd = 0;
- if (dma_buf) {
- if (gi2c->err)
- geni_i2c_rx_fsm_rst(gi2c);
- geni_se_rx_dma_unprep(se, rx_dma, len);
- i2c_put_dma_safe_msg_buf(dma_buf, msg, !gi2c->err);
- }
+ geni_i2c_rx_msg_cleanup(gi2c, cur);
return gi2c->err;
}
@@ -390,11 +443,12 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
u32 m_param)
{
- dma_addr_t tx_dma;
+ dma_addr_t tx_dma = 0;
unsigned long time_left;
void *dma_buf;
struct geni_se *se = &gi2c->se;
size_t len = msg->len;
+ struct i2c_msg *cur;
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);
if (dma_buf)
@@ -409,22 +463,21 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
geni_se_select_mode(se, GENI_SE_FIFO);
i2c_put_dma_safe_msg_buf(dma_buf, msg, false);
dma_buf = NULL;
+ } else {
+ gi2c->xfer_len = len;
+ gi2c->dma_addr = tx_dma;
+ gi2c->dma_buf = dma_buf;
}
if (!dma_buf) /* Get FIFO IRQ */
writel_relaxed(1, se->base + SE_GENI_TX_WATERMARK_REG);
+ cur = gi2c->cur;
time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT);
if (!time_left)
geni_i2c_abort_xfer(gi2c);
- gi2c->cur_wr = 0;
- if (dma_buf) {
- if (gi2c->err)
- geni_i2c_tx_fsm_rst(gi2c);
- geni_se_tx_dma_unprep(se, tx_dma, len);
- i2c_put_dma_safe_msg_buf(dma_buf, msg, !gi2c->err);
- }
+ geni_i2c_tx_msg_cleanup(gi2c, cur);
return gi2c->err;
}
@@ -623,6 +676,13 @@ static int geni_i2c_remove(struct platform_device *pdev)
return 0;
}
+static void geni_i2c_shutdown(struct platform_device *pdev)
+{
+ struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev);
+
+ geni_i2c_stop_xfer(gi2c);
+}
+
static int __maybe_unused geni_i2c_runtime_suspend(struct device *dev)
{
int ret;
@@ -687,6 +747,7 @@ MODULE_DEVICE_TABLE(of, geni_i2c_dt_match);
static struct platform_driver geni_i2c_driver = {
.probe = geni_i2c_probe,
.remove = geni_i2c_remove,
+ .shutdown = geni_i2c_shutdown,
.driver = {
.name = "geni_i2c",
.pm = &geni_i2c_pm_ops,
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 5a47915869ae..61dc20fd1191 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -1603,7 +1603,7 @@ out:
static u32 qup_i2c_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
+ return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL_ALL & ~I2C_FUNC_SMBUS_QUICK);
}
static const struct i2c_algorithm qup_i2c_algo = {
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index 217def2d7cb4..12f6d452c0f7 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -91,7 +91,6 @@
#define RCAR_BUS_PHASE_START (MDBS | MIE | ESG)
#define RCAR_BUS_PHASE_DATA (MDBS | MIE)
-#define RCAR_BUS_MASK_DATA (~(ESG | FSB) & 0xFF)
#define RCAR_BUS_PHASE_STOP (MDBS | MIE | FSB)
#define RCAR_IRQ_SEND (MNR | MAL | MST | MAT | MDE)
@@ -120,6 +119,7 @@ enum rcar_i2c_type {
};
struct rcar_i2c_priv {
+ u32 flags;
void __iomem *io;
struct i2c_adapter adap;
struct i2c_msg *msg;
@@ -130,7 +130,6 @@ struct rcar_i2c_priv {
int pos;
u32 icccr;
- u32 flags;
u8 recovery_icmcr; /* protected by adapter lock */
enum rcar_i2c_type devtype;
struct i2c_client *slave;
@@ -621,27 +620,16 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv)
/*
* This driver has a lock-free design because there are IP cores (at least
* R-Car Gen2) which have an inherent race condition in their hardware design.
- * There, we need to clear RCAR_BUS_MASK_DATA bits as soon as possible after
+ * There, we need to switch to RCAR_BUS_PHASE_DATA as soon as possible after
* the interrupt was generated, otherwise an unwanted repeated message gets
* generated. It turned out that taking a spinlock at the beginning of the ISR
* was already causing repeated messages. Thus, this driver was converted to
* the now lockless behaviour. Please keep this in mind when hacking the driver.
+ * R-Car Gen3 seems to have this fixed but earlier versions than R-Car Gen2 are
+ * likely affected. Therefore, we have different interrupt handler entries.
*/
-static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
+static irqreturn_t rcar_i2c_irq(int irq, struct rcar_i2c_priv *priv, u32 msr)
{
- struct rcar_i2c_priv *priv = ptr;
- u32 msr, val;
-
- /* Clear START or STOP immediately, except for REPSTART after read */
- if (likely(!(priv->flags & ID_P_REP_AFTER_RD))) {
- val = rcar_i2c_read(priv, ICMCR);
- rcar_i2c_write(priv, ICMCR, val & RCAR_BUS_MASK_DATA);
- }
-
- msr = rcar_i2c_read(priv, ICMSR);
-
- /* Only handle interrupts that are currently enabled */
- msr &= rcar_i2c_read(priv, ICMIER);
if (!msr) {
if (rcar_i2c_slave_irq(priv))
return IRQ_HANDLED;
@@ -685,6 +673,41 @@ out:
return IRQ_HANDLED;
}
+static irqreturn_t rcar_i2c_gen2_irq(int irq, void *ptr)
+{
+ struct rcar_i2c_priv *priv = ptr;
+ u32 msr;
+
+ /* Clear START or STOP immediately, except for REPSTART after read */
+ if (likely(!(priv->flags & ID_P_REP_AFTER_RD)))
+ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA);
+
+ /* Only handle interrupts that are currently enabled */
+ msr = rcar_i2c_read(priv, ICMSR);
+ msr &= rcar_i2c_read(priv, ICMIER);
+
+ return rcar_i2c_irq(irq, priv, msr);
+}
+
+static irqreturn_t rcar_i2c_gen3_irq(int irq, void *ptr)
+{
+ struct rcar_i2c_priv *priv = ptr;
+ u32 msr;
+
+ /* Only handle interrupts that are currently enabled */
+ msr = rcar_i2c_read(priv, ICMSR);
+ msr &= rcar_i2c_read(priv, ICMIER);
+
+ /*
+ * Clear START or STOP immediately, except for REPSTART after read or
+ * if a spurious interrupt was detected.
+ */
+ if (likely(!(priv->flags & ID_P_REP_AFTER_RD) && msr))
+ rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA);
+
+ return rcar_i2c_irq(irq, priv, msr);
+}
+
static struct dma_chan *rcar_i2c_request_dma_chan(struct device *dev,
enum dma_transfer_direction dir,
dma_addr_t port_addr)
@@ -931,6 +954,8 @@ static int rcar_i2c_probe(struct platform_device *pdev)
struct rcar_i2c_priv *priv;
struct i2c_adapter *adap;
struct device *dev = &pdev->dev;
+ unsigned long irqflags = 0;
+ irqreturn_t (*irqhandler)(int irq, void *ptr) = rcar_i2c_gen3_irq;
int ret;
/* Otherwise logic will break because some bytes must always use PIO */
@@ -979,6 +1004,11 @@ static int rcar_i2c_probe(struct platform_device *pdev)
rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */
+ if (priv->devtype < I2C_RCAR_GEN3) {
+ irqflags |= IRQF_NO_THREAD;
+ irqhandler = rcar_i2c_gen2_irq;
+ }
+
if (priv->devtype == I2C_RCAR_GEN3) {
priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (!IS_ERR(priv->rstc)) {
@@ -998,7 +1028,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)
priv->flags |= ID_P_HOST_NOTIFY;
priv->irq = platform_get_irq(pdev, 0);
- ret = devm_request_irq(dev, priv->irq, rcar_i2c_irq, 0, dev_name(dev), priv);
+ ret = devm_request_irq(dev, priv->irq, irqhandler, irqflags, dev_name(dev), priv);
if (ret < 0) {
dev_err(dev, "cannot get irq %d\n", priv->irq);
goto out_pm_disable;
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 3eafe0eb3e4c..62a903fbe912 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -781,7 +781,7 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
/* declare our i2c functionality */
static u32 s3c24xx_i2c_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART |
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL_ALL | I2C_FUNC_NOSTART |
I2C_FUNC_PROTOCOL_MANGLING;
}
diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c
deleted file mode 100644
index 30db8fafe078..000000000000
--- a/drivers/i2c/busses/i2c-sirf.c
+++ /dev/null
@@ -1,475 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * I2C bus driver for CSR SiRFprimaII
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- */
-
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#define SIRFSOC_I2C_CLK_CTRL 0x00
-#define SIRFSOC_I2C_STATUS 0x0C
-#define SIRFSOC_I2C_CTRL 0x10
-#define SIRFSOC_I2C_IO_CTRL 0x14
-#define SIRFSOC_I2C_SDA_DELAY 0x18
-#define SIRFSOC_I2C_CMD_START 0x1C
-#define SIRFSOC_I2C_CMD_BUF 0x30
-#define SIRFSOC_I2C_DATA_BUF 0x80
-
-#define SIRFSOC_I2C_CMD_BUF_MAX 16
-#define SIRFSOC_I2C_DATA_BUF_MAX 16
-
-#define SIRFSOC_I2C_CMD(x) (SIRFSOC_I2C_CMD_BUF + (x)*0x04)
-#define SIRFSOC_I2C_DATA_MASK(x) (0xFF<<(((x)&3)*8))
-#define SIRFSOC_I2C_DATA_SHIFT(x) (((x)&3)*8)
-
-#define SIRFSOC_I2C_DIV_MASK (0xFFFF)
-
-/* I2C status flags */
-#define SIRFSOC_I2C_STAT_BUSY BIT(0)
-#define SIRFSOC_I2C_STAT_TIP BIT(1)
-#define SIRFSOC_I2C_STAT_NACK BIT(2)
-#define SIRFSOC_I2C_STAT_TR_INT BIT(4)
-#define SIRFSOC_I2C_STAT_STOP BIT(6)
-#define SIRFSOC_I2C_STAT_CMD_DONE BIT(8)
-#define SIRFSOC_I2C_STAT_ERR BIT(9)
-#define SIRFSOC_I2C_CMD_INDEX (0x1F<<16)
-
-/* I2C control flags */
-#define SIRFSOC_I2C_RESET BIT(0)
-#define SIRFSOC_I2C_CORE_EN BIT(1)
-#define SIRFSOC_I2C_MASTER_MODE BIT(2)
-#define SIRFSOC_I2C_CMD_DONE_EN BIT(11)
-#define SIRFSOC_I2C_ERR_INT_EN BIT(12)
-
-#define SIRFSOC_I2C_SDA_DELAY_MASK (0xFF)
-#define SIRFSOC_I2C_SCLF_FILTER (3<<8)
-
-#define SIRFSOC_I2C_START_CMD BIT(0)
-
-#define SIRFSOC_I2C_CMD_RP(x) ((x)&0x7)
-#define SIRFSOC_I2C_NACK BIT(3)
-#define SIRFSOC_I2C_WRITE BIT(4)
-#define SIRFSOC_I2C_READ BIT(5)
-#define SIRFSOC_I2C_STOP BIT(6)
-#define SIRFSOC_I2C_START BIT(7)
-
-#define SIRFSOC_I2C_ERR_NOACK 1
-#define SIRFSOC_I2C_ERR_TIMEOUT 2
-
-struct sirfsoc_i2c {
- void __iomem *base;
- struct clk *clk;
- u32 cmd_ptr; /* Current position in CMD buffer */
- u8 *buf; /* Buffer passed by user */
- u32 msg_len; /* Message length */
- u32 finished_len; /* number of bytes read/written */
- u32 read_cmd_len; /* number of read cmd sent */
- int msg_read; /* 1 indicates a read message */
- int err_status; /* 1 indicates an error on bus */
-
- u32 sda_delay; /* For suspend/resume */
- u32 clk_div;
- int last; /* Last message in transfer, STOP cmd can be sent */
-
- struct completion done; /* indicates completion of message transfer */
- struct i2c_adapter adapter;
-};
-
-static void i2c_sirfsoc_read_data(struct sirfsoc_i2c *siic)
-{
- u32 data = 0;
- int i;
-
- for (i = 0; i < siic->read_cmd_len; i++) {
- if (!(i & 0x3))
- data = readl(siic->base + SIRFSOC_I2C_DATA_BUF + i);
- siic->buf[siic->finished_len++] =
- (u8)((data & SIRFSOC_I2C_DATA_MASK(i)) >>
- SIRFSOC_I2C_DATA_SHIFT(i));
- }
-}
-
-static void i2c_sirfsoc_queue_cmd(struct sirfsoc_i2c *siic)
-{
- u32 regval;
- int i = 0;
-
- if (siic->msg_read) {
- while (((siic->finished_len + i) < siic->msg_len)
- && (siic->cmd_ptr < SIRFSOC_I2C_CMD_BUF_MAX)) {
- regval = SIRFSOC_I2C_READ | SIRFSOC_I2C_CMD_RP(0);
- if (((siic->finished_len + i) ==
- (siic->msg_len - 1)) && siic->last)
- regval |= SIRFSOC_I2C_STOP | SIRFSOC_I2C_NACK;
- writel(regval,
- siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++));
- i++;
- }
-
- siic->read_cmd_len = i;
- } else {
- while ((siic->cmd_ptr < SIRFSOC_I2C_CMD_BUF_MAX - 1)
- && (siic->finished_len < siic->msg_len)) {
- regval = SIRFSOC_I2C_WRITE | SIRFSOC_I2C_CMD_RP(0);
- if ((siic->finished_len == (siic->msg_len - 1))
- && siic->last)
- regval |= SIRFSOC_I2C_STOP;
- writel(regval,
- siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++));
- writel(siic->buf[siic->finished_len++],
- siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++));
- }
- }
- siic->cmd_ptr = 0;
-
- /* Trigger the transfer */
- writel(SIRFSOC_I2C_START_CMD, siic->base + SIRFSOC_I2C_CMD_START);
-}
-
-static irqreturn_t i2c_sirfsoc_irq(int irq, void *dev_id)
-{
- struct sirfsoc_i2c *siic = (struct sirfsoc_i2c *)dev_id;
- u32 i2c_stat = readl(siic->base + SIRFSOC_I2C_STATUS);
-
- if (i2c_stat & SIRFSOC_I2C_STAT_ERR) {
- /* Error conditions */
- siic->err_status = SIRFSOC_I2C_ERR_NOACK;
- writel(SIRFSOC_I2C_STAT_ERR, siic->base + SIRFSOC_I2C_STATUS);
-
- if (i2c_stat & SIRFSOC_I2C_STAT_NACK)
- dev_dbg(&siic->adapter.dev, "ACK not received\n");
- else
- dev_err(&siic->adapter.dev, "I2C error\n");
-
- /*
- * Due to hardware ANOMALY, we need to reset I2C earlier after
- * we get NOACK while accessing non-existing clients, otherwise
- * we will get errors even we access existing clients later
- */
- writel(readl(siic->base + SIRFSOC_I2C_CTRL) | SIRFSOC_I2C_RESET,
- siic->base + SIRFSOC_I2C_CTRL);
- while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET)
- cpu_relax();
-
- complete(&siic->done);
- } else if (i2c_stat & SIRFSOC_I2C_STAT_CMD_DONE) {
- /* CMD buffer execution complete */
- if (siic->msg_read)
- i2c_sirfsoc_read_data(siic);
- if (siic->finished_len == siic->msg_len)
- complete(&siic->done);
- else /* Fill a new CMD buffer for left data */
- i2c_sirfsoc_queue_cmd(siic);
-
- writel(SIRFSOC_I2C_STAT_CMD_DONE, siic->base + SIRFSOC_I2C_STATUS);
- }
-
- return IRQ_HANDLED;
-}
-
-static void i2c_sirfsoc_set_address(struct sirfsoc_i2c *siic,
- struct i2c_msg *msg)
-{
- unsigned char addr;
- u32 regval = SIRFSOC_I2C_START | SIRFSOC_I2C_CMD_RP(0) | SIRFSOC_I2C_WRITE;
-
- /* no data and last message -> add STOP */
- if (siic->last && (msg->len == 0))
- regval |= SIRFSOC_I2C_STOP;
-
- writel(regval, siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++));
-
- addr = i2c_8bit_addr_from_msg(msg);
-
- /* Reverse direction bit */
- if (msg->flags & I2C_M_REV_DIR_ADDR)
- addr ^= 1;
-
- writel(addr, siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++));
-}
-
-static int i2c_sirfsoc_xfer_msg(struct sirfsoc_i2c *siic, struct i2c_msg *msg)
-{
- u32 regval = readl(siic->base + SIRFSOC_I2C_CTRL);
- /* timeout waiting for the xfer to finish or fail */
- int timeout = msecs_to_jiffies((msg->len + 1) * 50);
-
- i2c_sirfsoc_set_address(siic, msg);
-
- writel(regval | SIRFSOC_I2C_CMD_DONE_EN | SIRFSOC_I2C_ERR_INT_EN,
- siic->base + SIRFSOC_I2C_CTRL);
- i2c_sirfsoc_queue_cmd(siic);
-
- if (wait_for_completion_timeout(&siic->done, timeout) == 0) {
- siic->err_status = SIRFSOC_I2C_ERR_TIMEOUT;
- dev_err(&siic->adapter.dev, "Transfer timeout\n");
- }
-
- writel(regval & ~(SIRFSOC_I2C_CMD_DONE_EN | SIRFSOC_I2C_ERR_INT_EN),
- siic->base + SIRFSOC_I2C_CTRL);
- writel(0, siic->base + SIRFSOC_I2C_CMD_START);
-
- /* i2c control doesn't response, reset it */
- if (siic->err_status == SIRFSOC_I2C_ERR_TIMEOUT) {
- writel(readl(siic->base + SIRFSOC_I2C_CTRL) | SIRFSOC_I2C_RESET,
- siic->base + SIRFSOC_I2C_CTRL);
- while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET)
- cpu_relax();
- }
- return siic->err_status ? -EAGAIN : 0;
-}
-
-static u32 i2c_sirfsoc_func(struct i2c_adapter *adap)
-{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-}
-
-static int i2c_sirfsoc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
- int num)
-{
- struct sirfsoc_i2c *siic = adap->algo_data;
- int i, ret;
-
- clk_enable(siic->clk);
-
- for (i = 0; i < num; i++) {
- siic->buf = msgs[i].buf;
- siic->msg_len = msgs[i].len;
- siic->msg_read = !!(msgs[i].flags & I2C_M_RD);
- siic->err_status = 0;
- siic->cmd_ptr = 0;
- siic->finished_len = 0;
- siic->last = (i == (num - 1));
-
- ret = i2c_sirfsoc_xfer_msg(siic, &msgs[i]);
- if (ret) {
- clk_disable(siic->clk);
- return ret;
- }
- }
-
- clk_disable(siic->clk);
- return num;
-}
-
-/* I2C algorithms associated with this master controller driver */
-static const struct i2c_algorithm i2c_sirfsoc_algo = {
- .master_xfer = i2c_sirfsoc_xfer,
- .functionality = i2c_sirfsoc_func,
-};
-
-static int i2c_sirfsoc_probe(struct platform_device *pdev)
-{
- struct sirfsoc_i2c *siic;
- struct i2c_adapter *adap;
- struct clk *clk;
- int bitrate;
- int ctrl_speed;
- int irq;
-
- int err;
- u32 regval;
-
- clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(clk)) {
- err = PTR_ERR(clk);
- dev_err(&pdev->dev, "Clock get failed\n");
- goto err_get_clk;
- }
-
- err = clk_prepare(clk);
- if (err) {
- dev_err(&pdev->dev, "Clock prepare failed\n");
- goto err_clk_prep;
- }
-
- err = clk_enable(clk);
- if (err) {
- dev_err(&pdev->dev, "Clock enable failed\n");
- goto err_clk_en;
- }
-
- ctrl_speed = clk_get_rate(clk);
-
- siic = devm_kzalloc(&pdev->dev, sizeof(*siic), GFP_KERNEL);
- if (!siic) {
- err = -ENOMEM;
- goto out;
- }
- adap = &siic->adapter;
- adap->class = I2C_CLASS_DEPRECATED;
-
- siic->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(siic->base)) {
- err = PTR_ERR(siic->base);
- goto out;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- err = irq;
- goto out;
- }
- err = devm_request_irq(&pdev->dev, irq, i2c_sirfsoc_irq, 0,
- dev_name(&pdev->dev), siic);
- if (err)
- goto out;
-
- adap->algo = &i2c_sirfsoc_algo;
- adap->algo_data = siic;
- adap->retries = 3;
-
- adap->dev.of_node = pdev->dev.of_node;
- adap->dev.parent = &pdev->dev;
- adap->nr = pdev->id;
-
- strlcpy(adap->name, "sirfsoc-i2c", sizeof(adap->name));
-
- platform_set_drvdata(pdev, adap);
- init_completion(&siic->done);
-
- /* Controller initialisation */
-
- writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL);
- while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET)
- cpu_relax();
- writel(SIRFSOC_I2C_CORE_EN | SIRFSOC_I2C_MASTER_MODE,
- siic->base + SIRFSOC_I2C_CTRL);
-
- siic->clk = clk;
-
- err = of_property_read_u32(pdev->dev.of_node,
- "clock-frequency", &bitrate);
- if (err < 0)
- bitrate = I2C_MAX_STANDARD_MODE_FREQ;
-
- /*
- * Due to some hardware design issues, we need to tune the formula.
- * Since i2c is open drain interface that allows the slave to
- * stall the transaction by holding the SCL line at '0', the RTL
- * implementation is waiting for SCL feedback from the pin after
- * setting it to High-Z ('1'). This wait adds to the high-time
- * interval counter few cycles of the input synchronization
- * (depending on the SCL_FILTER_REG field), and also the time it
- * takes for the board pull-up resistor to rise the SCL line.
- * For slow SCL settings these additions are negligible,
- * but they start to affect the speed when clock is set to faster
- * frequencies.
- * Through the actual tests, use the different user_div value(which
- * in the divider formula 'Fio / (Fi2c * user_div)') to adapt
- * the different ranges of i2c bus clock frequency, to make the SCL
- * more accurate.
- */
- if (bitrate <= 30000)
- regval = ctrl_speed / (bitrate * 5);
- else if (bitrate > 30000 && bitrate <= 280000)
- regval = (2 * ctrl_speed) / (bitrate * 11);
- else
- regval = ctrl_speed / (bitrate * 6);
-
- writel(regval, siic->base + SIRFSOC_I2C_CLK_CTRL);
- if (regval > 0xFF)
- writel(0xFF, siic->base + SIRFSOC_I2C_SDA_DELAY);
- else
- writel(regval, siic->base + SIRFSOC_I2C_SDA_DELAY);
-
- err = i2c_add_numbered_adapter(adap);
- if (err < 0)
- goto out;
-
- clk_disable(clk);
-
- dev_info(&pdev->dev, " I2C adapter ready to operate\n");
-
- return 0;
-
-out:
- clk_disable(clk);
-err_clk_en:
- clk_unprepare(clk);
-err_clk_prep:
- clk_put(clk);
-err_get_clk:
- return err;
-}
-
-static int i2c_sirfsoc_remove(struct platform_device *pdev)
-{
- struct i2c_adapter *adapter = platform_get_drvdata(pdev);
- struct sirfsoc_i2c *siic = adapter->algo_data;
-
- writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL);
- i2c_del_adapter(adapter);
- clk_unprepare(siic->clk);
- clk_put(siic->clk);
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int i2c_sirfsoc_suspend(struct device *dev)
-{
- struct i2c_adapter *adapter = dev_get_drvdata(dev);
- struct sirfsoc_i2c *siic = adapter->algo_data;
-
- clk_enable(siic->clk);
- siic->sda_delay = readl(siic->base + SIRFSOC_I2C_SDA_DELAY);
- siic->clk_div = readl(siic->base + SIRFSOC_I2C_CLK_CTRL);
- clk_disable(siic->clk);
- return 0;
-}
-
-static int i2c_sirfsoc_resume(struct device *dev)
-{
- struct i2c_adapter *adapter = dev_get_drvdata(dev);
- struct sirfsoc_i2c *siic = adapter->algo_data;
-
- clk_enable(siic->clk);
- writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL);
- while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET)
- cpu_relax();
- writel(SIRFSOC_I2C_CORE_EN | SIRFSOC_I2C_MASTER_MODE,
- siic->base + SIRFSOC_I2C_CTRL);
- writel(siic->clk_div, siic->base + SIRFSOC_I2C_CLK_CTRL);
- writel(siic->sda_delay, siic->base + SIRFSOC_I2C_SDA_DELAY);
- clk_disable(siic->clk);
- return 0;
-}
-
-static const struct dev_pm_ops i2c_sirfsoc_pm_ops = {
- .suspend = i2c_sirfsoc_suspend,
- .resume = i2c_sirfsoc_resume,
-};
-#endif
-
-static const struct of_device_id sirfsoc_i2c_of_match[] = {
- { .compatible = "sirf,prima2-i2c", },
- {},
-};
-MODULE_DEVICE_TABLE(of, sirfsoc_i2c_of_match);
-
-static struct platform_driver i2c_sirfsoc_driver = {
- .driver = {
- .name = "sirfsoc_i2c",
-#ifdef CONFIG_PM
- .pm = &i2c_sirfsoc_pm_ops,
-#endif
- .of_match_table = sirfsoc_i2c_of_match,
- },
- .probe = i2c_sirfsoc_probe,
- .remove = i2c_sirfsoc_remove,
-};
-module_platform_driver(i2c_sirfsoc_driver);
-
-MODULE_DESCRIPTION("SiRF SoC I2C master controller driver");
-MODULE_AUTHOR("Zhiwu Song <Zhiwu.Song@csr.com>");
-MODULE_AUTHOR("Xiangzhen Ye <Xiangzhen.Ye@csr.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c
index 473fbe144b7e..c62c815b88eb 100644
--- a/drivers/i2c/busses/i2c-stm32f7.c
+++ b/drivers/i2c/busses/i2c-stm32f7.c
@@ -2035,12 +2035,8 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
}
irq_error = platform_get_irq(pdev, 1);
- if (irq_error <= 0) {
- if (irq_error != -EPROBE_DEFER)
- dev_err(&pdev->dev, "Failed to get IRQ error: %d\n",
- irq_error);
+ if (irq_error <= 0)
return irq_error ? : -ENOENT;
- }
i2c_dev->wakeup_src = of_property_read_bool(pdev->dev.of_node,
"wakeup-source");
diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c
deleted file mode 100644
index 64d739baf480..000000000000
--- a/drivers/i2c/busses/i2c-stu300.c
+++ /dev/null
@@ -1,1008 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2007-2012 ST-Ericsson AB
- * ST DDC I2C master mode driver, used in e.g. U300 series platforms.
- * Author: Linus Walleij <linus.walleij@stericsson.com>
- * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-/* the name of this kernel module */
-#define NAME "stu300"
-
-/* CR (Control Register) 8bit (R/W) */
-#define I2C_CR (0x00000000)
-#define I2C_CR_RESET_VALUE (0x00)
-#define I2C_CR_RESET_UMASK (0x00)
-#define I2C_CR_DDC1_ENABLE (0x80)
-#define I2C_CR_TRANS_ENABLE (0x40)
-#define I2C_CR_PERIPHERAL_ENABLE (0x20)
-#define I2C_CR_DDC2B_ENABLE (0x10)
-#define I2C_CR_START_ENABLE (0x08)
-#define I2C_CR_ACK_ENABLE (0x04)
-#define I2C_CR_STOP_ENABLE (0x02)
-#define I2C_CR_INTERRUPT_ENABLE (0x01)
-/* SR1 (Status Register 1) 8bit (R/-) */
-#define I2C_SR1 (0x00000004)
-#define I2C_SR1_RESET_VALUE (0x00)
-#define I2C_SR1_RESET_UMASK (0x00)
-#define I2C_SR1_EVF_IND (0x80)
-#define I2C_SR1_ADD10_IND (0x40)
-#define I2C_SR1_TRA_IND (0x20)
-#define I2C_SR1_BUSY_IND (0x10)
-#define I2C_SR1_BTF_IND (0x08)
-#define I2C_SR1_ADSL_IND (0x04)
-#define I2C_SR1_MSL_IND (0x02)
-#define I2C_SR1_SB_IND (0x01)
-/* SR2 (Status Register 2) 8bit (R/-) */
-#define I2C_SR2 (0x00000008)
-#define I2C_SR2_RESET_VALUE (0x00)
-#define I2C_SR2_RESET_UMASK (0x40)
-#define I2C_SR2_MASK (0xBF)
-#define I2C_SR2_SCLFAL_IND (0x80)
-#define I2C_SR2_ENDAD_IND (0x20)
-#define I2C_SR2_AF_IND (0x10)
-#define I2C_SR2_STOPF_IND (0x08)
-#define I2C_SR2_ARLO_IND (0x04)
-#define I2C_SR2_BERR_IND (0x02)
-#define I2C_SR2_DDC2BF_IND (0x01)
-/* CCR (Clock Control Register) 8bit (R/W) */
-#define I2C_CCR (0x0000000C)
-#define I2C_CCR_RESET_VALUE (0x00)
-#define I2C_CCR_RESET_UMASK (0x00)
-#define I2C_CCR_MASK (0xFF)
-#define I2C_CCR_FMSM (0x80)
-#define I2C_CCR_CC_MASK (0x7F)
-/* OAR1 (Own Address Register 1) 8bit (R/W) */
-#define I2C_OAR1 (0x00000010)
-#define I2C_OAR1_RESET_VALUE (0x00)
-#define I2C_OAR1_RESET_UMASK (0x00)
-#define I2C_OAR1_ADD_MASK (0xFF)
-/* OAR2 (Own Address Register 2) 8bit (R/W) */
-#define I2C_OAR2 (0x00000014)
-#define I2C_OAR2_RESET_VALUE (0x40)
-#define I2C_OAR2_RESET_UMASK (0x19)
-#define I2C_OAR2_MASK (0xE6)
-#define I2C_OAR2_FR_25_10MHZ (0x00)
-#define I2C_OAR2_FR_10_1667MHZ (0x20)
-#define I2C_OAR2_FR_1667_2667MHZ (0x40)
-#define I2C_OAR2_FR_2667_40MHZ (0x60)
-#define I2C_OAR2_FR_40_5333MHZ (0x80)
-#define I2C_OAR2_FR_5333_66MHZ (0xA0)
-#define I2C_OAR2_FR_66_80MHZ (0xC0)
-#define I2C_OAR2_FR_80_100MHZ (0xE0)
-#define I2C_OAR2_FR_MASK (0xE0)
-#define I2C_OAR2_ADD_MASK (0x06)
-/* DR (Data Register) 8bit (R/W) */
-#define I2C_DR (0x00000018)
-#define I2C_DR_RESET_VALUE (0x00)
-#define I2C_DR_RESET_UMASK (0xFF)
-#define I2C_DR_D_MASK (0xFF)
-/* ECCR (Extended Clock Control Register) 8bit (R/W) */
-#define I2C_ECCR (0x0000001C)
-#define I2C_ECCR_RESET_VALUE (0x00)
-#define I2C_ECCR_RESET_UMASK (0xE0)
-#define I2C_ECCR_MASK (0x1F)
-#define I2C_ECCR_CC_MASK (0x1F)
-
-/*
- * These events are more or less responses to commands
- * sent into the hardware, presumably reflecting the state
- * of an internal state machine.
- */
-enum stu300_event {
- STU300_EVENT_NONE = 0,
- STU300_EVENT_1,
- STU300_EVENT_2,
- STU300_EVENT_3,
- STU300_EVENT_4,
- STU300_EVENT_5,
- STU300_EVENT_6,
- STU300_EVENT_7,
- STU300_EVENT_8,
- STU300_EVENT_9
-};
-
-enum stu300_error {
- STU300_ERROR_NONE = 0,
- STU300_ERROR_ACKNOWLEDGE_FAILURE,
- STU300_ERROR_BUS_ERROR,
- STU300_ERROR_ARBITRATION_LOST,
- STU300_ERROR_UNKNOWN
-};
-
-/* timeout waiting for the controller to respond */
-#define STU300_TIMEOUT (msecs_to_jiffies(1000))
-
-/*
- * The number of address send athemps tried before giving up.
- * If the first one fails it seems like 5 to 8 attempts are required.
- */
-#define NUM_ADDR_RESEND_ATTEMPTS 12
-
-/* I2C clock speed, in Hz 0-400kHz*/
-static unsigned int scl_frequency = I2C_MAX_STANDARD_MODE_FREQ;
-module_param(scl_frequency, uint, 0644);
-
-/**
- * struct stu300_dev - the stu300 driver state holder
- * @pdev: parent platform device
- * @adapter: corresponding I2C adapter
- * @clk: hardware block clock
- * @irq: assigned interrupt line
- * @cmd_issue_lock: this locks the following cmd_ variables
- * @cmd_complete: acknowledge completion for an I2C command
- * @cmd_event: expected event coming in as a response to a command
- * @cmd_err: error code as response to a command
- * @speed: current bus speed in Hz
- * @msg_index: index of current message
- * @msg_len: length of current message
- */
-
-struct stu300_dev {
- struct platform_device *pdev;
- struct i2c_adapter adapter;
- void __iomem *virtbase;
- struct clk *clk;
- int irq;
- spinlock_t cmd_issue_lock;
- struct completion cmd_complete;
- enum stu300_event cmd_event;
- enum stu300_error cmd_err;
- unsigned int speed;
- int msg_index;
- int msg_len;
-};
-
-/* Local forward function declarations */
-static int stu300_init_hw(struct stu300_dev *dev);
-
-/*
- * The block needs writes in both MSW and LSW in order
- * for all data lines to reach their destination.
- */
-static inline void stu300_wr8(u32 value, void __iomem *address)
-{
- writel((value << 16) | value, address);
-}
-
-/*
- * This merely masks off the duplicates which appear
- * in bytes 1-3. You _MUST_ use 32-bit bus access on this
- * device, else it will not work.
- */
-static inline u32 stu300_r8(void __iomem *address)
-{
- return readl(address) & 0x000000FFU;
-}
-
-static void stu300_irq_enable(struct stu300_dev *dev)
-{
- u32 val;
- val = stu300_r8(dev->virtbase + I2C_CR);
- val |= I2C_CR_INTERRUPT_ENABLE;
- /* Twice paranoia (possible HW glitch) */
- stu300_wr8(val, dev->virtbase + I2C_CR);
- stu300_wr8(val, dev->virtbase + I2C_CR);
-}
-
-static void stu300_irq_disable(struct stu300_dev *dev)
-{
- u32 val;
- val = stu300_r8(dev->virtbase + I2C_CR);
- val &= ~I2C_CR_INTERRUPT_ENABLE;
- /* Twice paranoia (possible HW glitch) */
- stu300_wr8(val, dev->virtbase + I2C_CR);
- stu300_wr8(val, dev->virtbase + I2C_CR);
-}
-
-
-/*
- * Tells whether a certain event or events occurred in
- * response to a command. The events represent states in
- * the internal state machine of the hardware. The events
- * are not very well described in the hardware
- * documentation and can only be treated as abstract state
- * machine states.
- *
- * @ret 0 = event has not occurred or unknown error, any
- * other value means the correct event occurred or an error.
- */
-
-static int stu300_event_occurred(struct stu300_dev *dev,
- enum stu300_event mr_event) {
- u32 status1;
- u32 status2;
-
- /* What event happened? */
- status1 = stu300_r8(dev->virtbase + I2C_SR1);
-
- if (!(status1 & I2C_SR1_EVF_IND))
- /* No event at all */
- return 0;
-
- status2 = stu300_r8(dev->virtbase + I2C_SR2);
-
- /* Block any multiple interrupts */
- stu300_irq_disable(dev);
-
- /* Check for errors first */
- if (status2 & I2C_SR2_AF_IND) {
- dev->cmd_err = STU300_ERROR_ACKNOWLEDGE_FAILURE;
- return 1;
- } else if (status2 & I2C_SR2_BERR_IND) {
- dev->cmd_err = STU300_ERROR_BUS_ERROR;
- return 1;
- } else if (status2 & I2C_SR2_ARLO_IND) {
- dev->cmd_err = STU300_ERROR_ARBITRATION_LOST;
- return 1;
- }
-
- switch (mr_event) {
- case STU300_EVENT_1:
- if (status1 & I2C_SR1_ADSL_IND)
- return 1;
- break;
- case STU300_EVENT_2:
- case STU300_EVENT_3:
- case STU300_EVENT_7:
- case STU300_EVENT_8:
- if (status1 & I2C_SR1_BTF_IND) {
- return 1;
- }
- break;
- case STU300_EVENT_4:
- if (status2 & I2C_SR2_STOPF_IND)
- return 1;
- break;
- case STU300_EVENT_5:
- if (status1 & I2C_SR1_SB_IND)
- /* Clear start bit */
- return 1;
- break;
- case STU300_EVENT_6:
- if (status2 & I2C_SR2_ENDAD_IND) {
- /* First check for any errors */
- return 1;
- }
- break;
- case STU300_EVENT_9:
- if (status1 & I2C_SR1_ADD10_IND)
- return 1;
- break;
- default:
- break;
- }
- /* If we get here, we're on thin ice.
- * Here we are in a status where we have
- * gotten a response that does not match
- * what we requested.
- */
- dev->cmd_err = STU300_ERROR_UNKNOWN;
- dev_err(&dev->pdev->dev,
- "Unhandled interrupt! %d sr1: 0x%x sr2: 0x%x\n",
- mr_event, status1, status2);
- return 0;
-}
-
-static irqreturn_t stu300_irh(int irq, void *data)
-{
- struct stu300_dev *dev = data;
- int res;
-
- /* Just make sure that the block is clocked */
- clk_enable(dev->clk);
-
- /* See if this was what we were waiting for */
- spin_lock(&dev->cmd_issue_lock);
-
- res = stu300_event_occurred(dev, dev->cmd_event);
- if (res || dev->cmd_err != STU300_ERROR_NONE)
- complete(&dev->cmd_complete);
-
- spin_unlock(&dev->cmd_issue_lock);
-
- clk_disable(dev->clk);
-
- return IRQ_HANDLED;
-}
-
-/*
- * Sends a command and then waits for the bits masked by *flagmask*
- * to go high or low by IRQ awaiting.
- */
-static int stu300_start_and_await_event(struct stu300_dev *dev,
- u8 cr_value,
- enum stu300_event mr_event)
-{
- int ret;
-
- /* Lock command issue, fill in an event we wait for */
- spin_lock_irq(&dev->cmd_issue_lock);
- init_completion(&dev->cmd_complete);
- dev->cmd_err = STU300_ERROR_NONE;
- dev->cmd_event = mr_event;
- spin_unlock_irq(&dev->cmd_issue_lock);
-
- /* Turn on interrupt, send command and wait. */
- cr_value |= I2C_CR_INTERRUPT_ENABLE;
- stu300_wr8(cr_value, dev->virtbase + I2C_CR);
- ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
- STU300_TIMEOUT);
- if (ret < 0) {
- dev_err(&dev->pdev->dev,
- "wait_for_completion_interruptible_timeout() "
- "returned %d waiting for event %04x\n", ret, mr_event);
- return ret;
- }
-
- if (ret == 0) {
- dev_err(&dev->pdev->dev, "controller timed out "
- "waiting for event %d, reinit hardware\n", mr_event);
- (void) stu300_init_hw(dev);
- return -ETIMEDOUT;
- }
-
- if (dev->cmd_err != STU300_ERROR_NONE) {
- dev_err(&dev->pdev->dev, "controller (start) "
- "error %d waiting for event %d, reinit hardware\n",
- dev->cmd_err, mr_event);
- (void) stu300_init_hw(dev);
- return -EIO;
- }
-
- return 0;
-}
-
-/*
- * This waits for a flag to be set, if it is not set on entry, an interrupt is
- * configured to wait for the flag using a completion.
- */
-static int stu300_await_event(struct stu300_dev *dev,
- enum stu300_event mr_event)
-{
- int ret;
-
- /* Is it already here? */
- spin_lock_irq(&dev->cmd_issue_lock);
- dev->cmd_err = STU300_ERROR_NONE;
- dev->cmd_event = mr_event;
-
- init_completion(&dev->cmd_complete);
-
- /* Turn on the I2C interrupt for current operation */
- stu300_irq_enable(dev);
-
- /* Unlock the command block and wait for the event to occur */
- spin_unlock_irq(&dev->cmd_issue_lock);
-
- ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
- STU300_TIMEOUT);
- if (ret < 0) {
- dev_err(&dev->pdev->dev,
- "wait_for_completion_interruptible_timeout()"
- "returned %d waiting for event %04x\n", ret, mr_event);
- return ret;
- }
-
- if (ret == 0) {
- if (mr_event != STU300_EVENT_6) {
- dev_err(&dev->pdev->dev, "controller "
- "timed out waiting for event %d, reinit "
- "hardware\n", mr_event);
- (void) stu300_init_hw(dev);
- }
- return -ETIMEDOUT;
- }
-
- if (dev->cmd_err != STU300_ERROR_NONE) {
- if (mr_event != STU300_EVENT_6) {
- dev_err(&dev->pdev->dev, "controller "
- "error (await_event) %d waiting for event %d, "
- "reinit hardware\n", dev->cmd_err, mr_event);
- (void) stu300_init_hw(dev);
- }
- return -EIO;
- }
-
- return 0;
-}
-
-/*
- * Waits for the busy bit to go low by repeated polling.
- */
-#define BUSY_RELEASE_ATTEMPTS 10
-static int stu300_wait_while_busy(struct stu300_dev *dev)
-{
- unsigned long timeout;
- int i;
-
- for (i = 0; i < BUSY_RELEASE_ATTEMPTS; i++) {
- timeout = jiffies + STU300_TIMEOUT;
-
- while (!time_after(jiffies, timeout)) {
- /* Is not busy? */
- if ((stu300_r8(dev->virtbase + I2C_SR1) &
- I2C_SR1_BUSY_IND) == 0)
- return 0;
- msleep(1);
- }
-
- dev_err(&dev->pdev->dev, "transaction timed out "
- "waiting for device to be free (not busy). "
- "Attempt: %d\n", i+1);
-
- dev_err(&dev->pdev->dev, "base address = "
- "0x%p, reinit hardware\n", dev->virtbase);
-
- (void) stu300_init_hw(dev);
- }
-
- dev_err(&dev->pdev->dev, "giving up after %d attempts "
- "to reset the bus.\n", BUSY_RELEASE_ATTEMPTS);
-
- return -ETIMEDOUT;
-}
-
-struct stu300_clkset {
- unsigned long rate;
- u32 setting;
-};
-
-static const struct stu300_clkset stu300_clktable[] = {
- { 0, 0xFFU },
- { 2500000, I2C_OAR2_FR_25_10MHZ },
- { 10000000, I2C_OAR2_FR_10_1667MHZ },
- { 16670000, I2C_OAR2_FR_1667_2667MHZ },
- { 26670000, I2C_OAR2_FR_2667_40MHZ },
- { 40000000, I2C_OAR2_FR_40_5333MHZ },
- { 53330000, I2C_OAR2_FR_5333_66MHZ },
- { 66000000, I2C_OAR2_FR_66_80MHZ },
- { 80000000, I2C_OAR2_FR_80_100MHZ },
- { 100000000, 0xFFU },
-};
-
-
-static int stu300_set_clk(struct stu300_dev *dev, unsigned long clkrate)
-{
-
- u32 val;
- int i = 0;
-
- /* Locate the appropriate clock setting */
- while (i < ARRAY_SIZE(stu300_clktable) - 1 &&
- stu300_clktable[i].rate < clkrate)
- i++;
-
- if (stu300_clktable[i].setting == 0xFFU) {
- dev_err(&dev->pdev->dev, "too %s clock rate requested "
- "(%lu Hz).\n", i ? "high" : "low", clkrate);
- return -EINVAL;
- }
-
- stu300_wr8(stu300_clktable[i].setting,
- dev->virtbase + I2C_OAR2);
-
- dev_dbg(&dev->pdev->dev, "Clock rate %lu Hz, I2C bus speed %d Hz "
- "virtbase %p\n", clkrate, dev->speed, dev->virtbase);
-
- if (dev->speed > I2C_MAX_STANDARD_MODE_FREQ)
- /* Fast Mode I2C */
- val = ((clkrate/dev->speed) - 9)/3 + 1;
- else
- /* Standard Mode I2C */
- val = ((clkrate/dev->speed) - 7)/2 + 1;
-
- /* According to spec the divider must be > 2 */
- if (val < 0x002) {
- dev_err(&dev->pdev->dev, "too low clock rate (%lu Hz).\n",
- clkrate);
- return -EINVAL;
- }
-
- /* We have 12 bits clock divider only! */
- if (val & 0xFFFFF000U) {
- dev_err(&dev->pdev->dev, "too high clock rate (%lu Hz).\n",
- clkrate);
- return -EINVAL;
- }
-
- if (dev->speed > I2C_MAX_STANDARD_MODE_FREQ) {
- /* CC6..CC0 */
- stu300_wr8((val & I2C_CCR_CC_MASK) | I2C_CCR_FMSM,
- dev->virtbase + I2C_CCR);
- dev_dbg(&dev->pdev->dev, "set clock divider to 0x%08x, "
- "Fast Mode I2C\n", val);
- } else {
- /* CC6..CC0 */
- stu300_wr8((val & I2C_CCR_CC_MASK),
- dev->virtbase + I2C_CCR);
- dev_dbg(&dev->pdev->dev, "set clock divider to "
- "0x%08x, Standard Mode I2C\n", val);
- }
-
- /* CC11..CC7 */
- stu300_wr8(((val >> 7) & 0x1F),
- dev->virtbase + I2C_ECCR);
-
- return 0;
-}
-
-
-static int stu300_init_hw(struct stu300_dev *dev)
-{
- u32 dummy;
- unsigned long clkrate;
- int ret;
-
- /* Disable controller */
- stu300_wr8(0x00, dev->virtbase + I2C_CR);
- /*
- * Set own address to some default value (0x00).
- * We do not support slave mode anyway.
- */
- stu300_wr8(0x00, dev->virtbase + I2C_OAR1);
- /*
- * The I2C controller only operates properly in 26 MHz but we
- * program this driver as if we didn't know. This will also set the two
- * high bits of the own address to zero as well.
- * There is no known hardware issue with running in 13 MHz
- * However, speeds over 200 kHz are not used.
- */
- clkrate = clk_get_rate(dev->clk);
- ret = stu300_set_clk(dev, clkrate);
-
- if (ret)
- return ret;
- /*
- * Enable block, do it TWICE (hardware glitch)
- * Setting bit 7 can enable DDC mode. (Not used currently.)
- */
- stu300_wr8(I2C_CR_PERIPHERAL_ENABLE,
- dev->virtbase + I2C_CR);
- stu300_wr8(I2C_CR_PERIPHERAL_ENABLE,
- dev->virtbase + I2C_CR);
- /* Make a dummy read of the status register SR1 & SR2 */
- dummy = stu300_r8(dev->virtbase + I2C_SR2);
- dummy = stu300_r8(dev->virtbase + I2C_SR1);
-
- return 0;
-}
-
-
-
-/* Send slave address. */
-static int stu300_send_address(struct stu300_dev *dev,
- struct i2c_msg *msg, int resend)
-{
- u32 val;
- int ret;
-
- if (msg->flags & I2C_M_TEN) {
- /* This is probably how 10 bit addresses look */
- val = (0xf0 | (((u32) msg->addr & 0x300) >> 7)) &
- I2C_DR_D_MASK;
- if (msg->flags & I2C_M_RD)
- /* This is the direction bit */
- val |= 0x01;
- } else {
- val = i2c_8bit_addr_from_msg(msg);
- }
-
- if (resend) {
- if (msg->flags & I2C_M_RD)
- dev_dbg(&dev->pdev->dev, "read resend\n");
- else
- dev_dbg(&dev->pdev->dev, "write resend\n");
- }
-
- stu300_wr8(val, dev->virtbase + I2C_DR);
-
- /* For 10bit addressing, await 10bit request (EVENT 9) */
- if (msg->flags & I2C_M_TEN) {
- ret = stu300_await_event(dev, STU300_EVENT_9);
- /*
- * The slave device wants a 10bit address, send the rest
- * of the bits (the LSBits)
- */
- val = msg->addr & I2C_DR_D_MASK;
- /* This clears "event 9" */
- stu300_wr8(val, dev->virtbase + I2C_DR);
- if (ret != 0)
- return ret;
- }
- /* FIXME: Why no else here? two events for 10bit?
- * Await event 6 (normal) or event 9 (10bit)
- */
-
- if (resend)
- dev_dbg(&dev->pdev->dev, "await event 6\n");
- ret = stu300_await_event(dev, STU300_EVENT_6);
-
- /*
- * Clear any pending EVENT 6 no matter what happened during
- * await_event.
- */
- val = stu300_r8(dev->virtbase + I2C_CR);
- val |= I2C_CR_PERIPHERAL_ENABLE;
- stu300_wr8(val, dev->virtbase + I2C_CR);
-
- return ret;
-}
-
-static int stu300_xfer_msg(struct i2c_adapter *adap,
- struct i2c_msg *msg, int stop)
-{
- u32 cr;
- u32 val;
- u32 i;
- int ret;
- int attempts = 0;
- struct stu300_dev *dev = i2c_get_adapdata(adap);
-
- clk_enable(dev->clk);
-
- /* Remove this if (0) to trace each and every message. */
- if (0) {
- dev_dbg(&dev->pdev->dev, "I2C message to: 0x%04x, len: %d, "
- "flags: 0x%04x, stop: %d\n",
- msg->addr, msg->len, msg->flags, stop);
- }
-
- /*
- * For some reason, sending the address sometimes fails when running
- * on the 13 MHz clock. No interrupt arrives. This is a work around,
- * which tries to restart and send the address up to 10 times before
- * really giving up. Usually 5 to 8 attempts are enough.
- */
- do {
- if (attempts)
- dev_dbg(&dev->pdev->dev, "wait while busy\n");
- /* Check that the bus is free, or wait until some timeout */
- ret = stu300_wait_while_busy(dev);
- if (ret != 0)
- goto exit_disable;
-
- if (attempts)
- dev_dbg(&dev->pdev->dev, "re-int hw\n");
- /*
- * According to ST, there is no problem if the clock is
- * changed between 13 and 26 MHz during a transfer.
- */
- ret = stu300_init_hw(dev);
- if (ret)
- goto exit_disable;
-
- /* Send a start condition */
- cr = I2C_CR_PERIPHERAL_ENABLE;
- /* Setting the START bit puts the block in master mode */
- if (!(msg->flags & I2C_M_NOSTART))
- cr |= I2C_CR_START_ENABLE;
- if ((msg->flags & I2C_M_RD) && (msg->len > 1))
- /* On read more than 1 byte, we need ack. */
- cr |= I2C_CR_ACK_ENABLE;
- /* Check that it gets through */
- if (!(msg->flags & I2C_M_NOSTART)) {
- if (attempts)
- dev_dbg(&dev->pdev->dev, "send start event\n");
- ret = stu300_start_and_await_event(dev, cr,
- STU300_EVENT_5);
- }
-
- if (attempts)
- dev_dbg(&dev->pdev->dev, "send address\n");
-
- if (ret == 0)
- /* Send address */
- ret = stu300_send_address(dev, msg, attempts != 0);
-
- if (ret != 0) {
- attempts++;
- dev_dbg(&dev->pdev->dev, "failed sending address, "
- "retrying. Attempt: %d msg_index: %d/%d\n",
- attempts, dev->msg_index, dev->msg_len);
- }
-
- } while (ret != 0 && attempts < NUM_ADDR_RESEND_ATTEMPTS);
-
- if (attempts < NUM_ADDR_RESEND_ATTEMPTS && attempts > 0) {
- dev_dbg(&dev->pdev->dev, "managed to get address "
- "through after %d attempts\n", attempts);
- } else if (attempts == NUM_ADDR_RESEND_ATTEMPTS) {
- dev_dbg(&dev->pdev->dev, "I give up, tried %d times "
- "to resend address.\n",
- NUM_ADDR_RESEND_ATTEMPTS);
- goto exit_disable;
- }
-
-
- if (msg->flags & I2C_M_RD) {
- /* READ: we read the actual bytes one at a time */
- for (i = 0; i < msg->len; i++) {
- if (i == msg->len-1) {
- /*
- * Disable ACK and set STOP condition before
- * reading last byte
- */
- val = I2C_CR_PERIPHERAL_ENABLE;
-
- if (stop)
- val |= I2C_CR_STOP_ENABLE;
-
- stu300_wr8(val,
- dev->virtbase + I2C_CR);
- }
- /* Wait for this byte... */
- ret = stu300_await_event(dev, STU300_EVENT_7);
- if (ret != 0)
- goto exit_disable;
- /* This clears event 7 */
- msg->buf[i] = (u8) stu300_r8(dev->virtbase + I2C_DR);
- }
- } else {
- /* WRITE: we send the actual bytes one at a time */
- for (i = 0; i < msg->len; i++) {
- /* Write the byte */
- stu300_wr8(msg->buf[i],
- dev->virtbase + I2C_DR);
- /* Check status */
- ret = stu300_await_event(dev, STU300_EVENT_8);
- /* Next write to DR will clear event 8 */
- if (ret != 0) {
- dev_err(&dev->pdev->dev, "error awaiting "
- "event 8 (%d)\n", ret);
- goto exit_disable;
- }
- }
- /* Check NAK */
- if (!(msg->flags & I2C_M_IGNORE_NAK)) {
- if (stu300_r8(dev->virtbase + I2C_SR2) &
- I2C_SR2_AF_IND) {
- dev_err(&dev->pdev->dev, "I2C payload "
- "send returned NAK!\n");
- ret = -EIO;
- goto exit_disable;
- }
- }
- if (stop) {
- /* Send stop condition */
- val = I2C_CR_PERIPHERAL_ENABLE;
- val |= I2C_CR_STOP_ENABLE;
- stu300_wr8(val, dev->virtbase + I2C_CR);
- }
- }
-
- /* Check that the bus is free, or wait until some timeout occurs */
- ret = stu300_wait_while_busy(dev);
- if (ret != 0) {
- dev_err(&dev->pdev->dev, "timeout waiting for transfer "
- "to commence.\n");
- goto exit_disable;
- }
-
- /* Dummy read status registers */
- val = stu300_r8(dev->virtbase + I2C_SR2);
- val = stu300_r8(dev->virtbase + I2C_SR1);
- ret = 0;
-
- exit_disable:
- /* Disable controller */
- stu300_wr8(0x00, dev->virtbase + I2C_CR);
- clk_disable(dev->clk);
- return ret;
-}
-
-static int stu300_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
- int num)
-{
- int ret = -1;
- int i;
-
- struct stu300_dev *dev = i2c_get_adapdata(adap);
- dev->msg_len = num;
-
- for (i = 0; i < num; i++) {
- /*
- * Another driver appears to send stop for each message,
- * here we only do that for the last message. Possibly some
- * peripherals require this behaviour, then their drivers
- * have to send single messages in order to get "stop" for
- * each message.
- */
- dev->msg_index = i;
-
- ret = stu300_xfer_msg(adap, &msgs[i], (i == (num - 1)));
-
- if (ret != 0) {
- num = ret;
- break;
- }
- }
-
- return num;
-}
-
-static int stu300_xfer_todo(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
-{
- /* TODO: implement polling for this case if need be. */
- WARN(1, "%s: atomic transfers not implemented\n", dev_name(&adap->dev));
- return -EOPNOTSUPP;
-}
-
-static u32 stu300_func(struct i2c_adapter *adap)
-{
- /* This is the simplest thing you can think of... */
- return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR;
-}
-
-static const struct i2c_algorithm stu300_algo = {
- .master_xfer = stu300_xfer,
- .master_xfer_atomic = stu300_xfer_todo,
- .functionality = stu300_func,
-};
-
-static const struct i2c_adapter_quirks stu300_quirks = {
- .flags = I2C_AQ_NO_ZERO_LEN,
-};
-
-static int stu300_probe(struct platform_device *pdev)
-{
- struct stu300_dev *dev;
- struct i2c_adapter *adap;
- int bus_nr;
- int ret = 0;
-
- dev = devm_kzalloc(&pdev->dev, sizeof(struct stu300_dev), GFP_KERNEL);
- if (!dev)
- return -ENOMEM;
-
- bus_nr = pdev->id;
- dev->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(dev->clk)) {
- dev_err(&pdev->dev, "could not retrieve i2c bus clock\n");
- return PTR_ERR(dev->clk);
- }
-
- dev->pdev = pdev;
- dev->virtbase = devm_platform_ioremap_resource(pdev, 0);
- dev_dbg(&pdev->dev, "initialize bus device I2C%d on virtual "
- "base %p\n", bus_nr, dev->virtbase);
- if (IS_ERR(dev->virtbase))
- return PTR_ERR(dev->virtbase);
-
- dev->irq = platform_get_irq(pdev, 0);
- ret = devm_request_irq(&pdev->dev, dev->irq, stu300_irh, 0, NAME, dev);
- if (ret < 0)
- return ret;
-
- dev->speed = scl_frequency;
-
- clk_prepare_enable(dev->clk);
- ret = stu300_init_hw(dev);
- clk_disable(dev->clk);
- if (ret != 0) {
- dev_err(&dev->pdev->dev, "error initializing hardware.\n");
- return -EIO;
- }
-
- /* IRQ event handling initialization */
- spin_lock_init(&dev->cmd_issue_lock);
- dev->cmd_event = STU300_EVENT_NONE;
- dev->cmd_err = STU300_ERROR_NONE;
-
- adap = &dev->adapter;
- adap->owner = THIS_MODULE;
- /* DDC class but actually often used for more generic I2C */
- adap->class = I2C_CLASS_DEPRECATED;
- strlcpy(adap->name, "ST Microelectronics DDC I2C adapter",
- sizeof(adap->name));
- adap->nr = bus_nr;
- adap->algo = &stu300_algo;
- adap->dev.parent = &pdev->dev;
- adap->dev.of_node = pdev->dev.of_node;
- adap->quirks = &stu300_quirks;
-
- i2c_set_adapdata(adap, dev);
-
- /* i2c device drivers may be active on return from add_adapter() */
- ret = i2c_add_numbered_adapter(adap);
- if (ret)
- return ret;
-
- platform_set_drvdata(pdev, dev);
- dev_info(&pdev->dev, "ST DDC I2C @ %p, irq %d\n",
- dev->virtbase, dev->irq);
-
- return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int stu300_suspend(struct device *device)
-{
- struct stu300_dev *dev = dev_get_drvdata(device);
-
- /* Turn off everything */
- stu300_wr8(0x00, dev->virtbase + I2C_CR);
- return 0;
-}
-
-static int stu300_resume(struct device *device)
-{
- int ret = 0;
- struct stu300_dev *dev = dev_get_drvdata(device);
-
- clk_enable(dev->clk);
- ret = stu300_init_hw(dev);
- clk_disable(dev->clk);
-
- if (ret != 0)
- dev_err(device, "error re-initializing hardware.\n");
- return ret;
-}
-
-static SIMPLE_DEV_PM_OPS(stu300_pm, stu300_suspend, stu300_resume);
-#define STU300_I2C_PM (&stu300_pm)
-#else
-#define STU300_I2C_PM NULL
-#endif
-
-static int stu300_remove(struct platform_device *pdev)
-{
- struct stu300_dev *dev = platform_get_drvdata(pdev);
-
- i2c_del_adapter(&dev->adapter);
- /* Turn off everything */
- stu300_wr8(0x00, dev->virtbase + I2C_CR);
- return 0;
-}
-
-static const struct of_device_id stu300_dt_match[] = {
- { .compatible = "st,ddci2c" },
- {},
-};
-MODULE_DEVICE_TABLE(of, stu300_dt_match);
-
-static struct platform_driver stu300_i2c_driver = {
- .driver = {
- .name = NAME,
- .pm = STU300_I2C_PM,
- .of_match_table = stu300_dt_match,
- },
- .probe = stu300_probe,
- .remove = stu300_remove,
-
-};
-
-static int __init stu300_init(void)
-{
- return platform_driver_register(&stu300_i2c_driver);
-}
-
-static void __exit stu300_exit(void)
-{
- platform_driver_unregister(&stu300_i2c_driver);
-}
-
-/*
- * The systems using this bus often have very basic devices such
- * as regulators on the I2C bus, so this needs to be loaded early.
- * Therefore it is registered in the subsys_initcall().
- */
-subsys_initcall(stu300_init);
-module_exit(stu300_exit);
-
-MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
-MODULE_DESCRIPTION("ST Micro DDC I2C adapter (" NAME ")");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" NAME);
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 8b113ae32dc7..c883044715f3 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -550,7 +550,7 @@ static int tegra_i2c_poll_register(struct tegra_i2c_dev *i2c_dev,
void __iomem *addr = i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg);
u32 val;
- if (!i2c_dev->atomic_mode && !in_irq())
+ if (!i2c_dev->atomic_mode)
return readl_relaxed_poll_timeout(addr, val, !(val & mask),
delay_us, timeout_us);
@@ -1739,9 +1739,10 @@ static int tegra_i2c_probe(struct platform_device *pdev)
/* interrupt will be enabled during of transfer time */
irq_set_status_flags(i2c_dev->irq, IRQ_NOAUTOEN);
- err = devm_request_irq(i2c_dev->dev, i2c_dev->irq, tegra_i2c_isr,
- IRQF_NO_SUSPEND, dev_name(i2c_dev->dev),
- i2c_dev);
+ err = devm_request_threaded_irq(i2c_dev->dev, i2c_dev->irq,
+ NULL, tegra_i2c_isr,
+ IRQF_NO_SUSPEND | IRQF_ONESHOT,
+ dev_name(i2c_dev->dev), i2c_dev);
if (err)
return err;
diff --git a/drivers/i2c/busses/i2c-zx2967.c b/drivers/i2c/busses/i2c-zx2967.c
deleted file mode 100644
index 8db9519695a6..000000000000
--- a/drivers/i2c/busses/i2c-zx2967.c
+++ /dev/null
@@ -1,602 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2017 Sanechips Technology Co., Ltd.
- * Copyright 2017 Linaro Ltd.
- *
- * Author: Baoyou Xie <baoyou.xie@linaro.org>
- */
-
-#include <linux/clk.h>
-#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-
-#define REG_CMD 0x04
-#define REG_DEVADDR_H 0x0C
-#define REG_DEVADDR_L 0x10
-#define REG_CLK_DIV_FS 0x14
-#define REG_CLK_DIV_HS 0x18
-#define REG_WRCONF 0x1C
-#define REG_RDCONF 0x20
-#define REG_DATA 0x24
-#define REG_STAT 0x28
-
-#define I2C_STOP 0
-#define I2C_MASTER BIT(0)
-#define I2C_ADDR_MODE_TEN BIT(1)
-#define I2C_IRQ_MSK_ENABLE BIT(3)
-#define I2C_RW_READ BIT(4)
-#define I2C_CMB_RW_EN BIT(5)
-#define I2C_START BIT(6)
-
-#define I2C_ADDR_LOW_MASK GENMASK(6, 0)
-#define I2C_ADDR_LOW_SHIFT 0
-#define I2C_ADDR_HI_MASK GENMASK(2, 0)
-#define I2C_ADDR_HI_SHIFT 7
-
-#define I2C_WFIFO_RESET BIT(7)
-#define I2C_RFIFO_RESET BIT(7)
-
-#define I2C_IRQ_ACK_CLEAR BIT(7)
-#define I2C_INT_MASK GENMASK(6, 0)
-
-#define I2C_TRANS_DONE BIT(0)
-#define I2C_SR_EDEVICE BIT(1)
-#define I2C_SR_EDATA BIT(2)
-
-#define I2C_FIFO_MAX 16
-
-#define I2C_TIMEOUT msecs_to_jiffies(1000)
-
-#define DEV(i2c) ((i2c)->adap.dev.parent)
-
-struct zx2967_i2c {
- struct i2c_adapter adap;
- struct clk *clk;
- struct completion complete;
- u32 clk_freq;
- void __iomem *reg_base;
- size_t residue;
- int irq;
- int msg_rd;
- u8 *cur_trans;
- u8 access_cnt;
- int error;
-};
-
-static void zx2967_i2c_writel(struct zx2967_i2c *i2c,
- u32 val, unsigned long reg)
-{
- writel_relaxed(val, i2c->reg_base + reg);
-}
-
-static u32 zx2967_i2c_readl(struct zx2967_i2c *i2c, unsigned long reg)
-{
- return readl_relaxed(i2c->reg_base + reg);
-}
-
-static void zx2967_i2c_writesb(struct zx2967_i2c *i2c,
- void *data, unsigned long reg, int len)
-{
- writesb(i2c->reg_base + reg, data, len);
-}
-
-static void zx2967_i2c_readsb(struct zx2967_i2c *i2c,
- void *data, unsigned long reg, int len)
-{
- readsb(i2c->reg_base + reg, data, len);
-}
-
-static void zx2967_i2c_start_ctrl(struct zx2967_i2c *i2c)
-{
- u32 status;
- u32 ctl;
-
- status = zx2967_i2c_readl(i2c, REG_STAT);
- status |= I2C_IRQ_ACK_CLEAR;
- zx2967_i2c_writel(i2c, status, REG_STAT);
-
- ctl = zx2967_i2c_readl(i2c, REG_CMD);
- if (i2c->msg_rd)
- ctl |= I2C_RW_READ;
- else
- ctl &= ~I2C_RW_READ;
- ctl &= ~I2C_CMB_RW_EN;
- ctl |= I2C_START;
- zx2967_i2c_writel(i2c, ctl, REG_CMD);
-}
-
-static void zx2967_i2c_flush_fifos(struct zx2967_i2c *i2c)
-{
- u32 offset;
- u32 val;
-
- if (i2c->msg_rd) {
- offset = REG_RDCONF;
- val = I2C_RFIFO_RESET;
- } else {
- offset = REG_WRCONF;
- val = I2C_WFIFO_RESET;
- }
-
- val |= zx2967_i2c_readl(i2c, offset);
- zx2967_i2c_writel(i2c, val, offset);
-}
-
-static int zx2967_i2c_empty_rx_fifo(struct zx2967_i2c *i2c, u32 size)
-{
- u8 val[I2C_FIFO_MAX] = {0};
- int i;
-
- if (size > I2C_FIFO_MAX) {
- dev_err(DEV(i2c), "fifo size %d over the max value %d\n",
- size, I2C_FIFO_MAX);
- return -EINVAL;
- }
-
- zx2967_i2c_readsb(i2c, val, REG_DATA, size);
- for (i = 0; i < size; i++) {
- *i2c->cur_trans++ = val[i];
- i2c->residue--;
- }
-
- barrier();
-
- return 0;
-}
-
-static int zx2967_i2c_fill_tx_fifo(struct zx2967_i2c *i2c)
-{
- size_t residue = i2c->residue;
- u8 *buf = i2c->cur_trans;
-
- if (residue == 0) {
- dev_err(DEV(i2c), "residue is %d\n", (int)residue);
- return -EINVAL;
- }
-
- if (residue <= I2C_FIFO_MAX) {
- zx2967_i2c_writesb(i2c, buf, REG_DATA, residue);
-
- /* Again update before writing to FIFO to make sure isr sees. */
- i2c->residue = 0;
- i2c->cur_trans = NULL;
- } else {
- zx2967_i2c_writesb(i2c, buf, REG_DATA, I2C_FIFO_MAX);
- i2c->residue -= I2C_FIFO_MAX;
- i2c->cur_trans += I2C_FIFO_MAX;
- }
-
- barrier();
-
- return 0;
-}
-
-static int zx2967_i2c_reset_hardware(struct zx2967_i2c *i2c)
-{
- u32 val;
- u32 clk_div;
-
- val = I2C_MASTER | I2C_IRQ_MSK_ENABLE;
- zx2967_i2c_writel(i2c, val, REG_CMD);
-
- clk_div = clk_get_rate(i2c->clk) / i2c->clk_freq - 1;
- zx2967_i2c_writel(i2c, clk_div, REG_CLK_DIV_FS);
- zx2967_i2c_writel(i2c, clk_div, REG_CLK_DIV_HS);
-
- zx2967_i2c_writel(i2c, I2C_FIFO_MAX - 1, REG_WRCONF);
- zx2967_i2c_writel(i2c, I2C_FIFO_MAX - 1, REG_RDCONF);
- zx2967_i2c_writel(i2c, 1, REG_RDCONF);
-
- zx2967_i2c_flush_fifos(i2c);
-
- return 0;
-}
-
-static void zx2967_i2c_isr_clr(struct zx2967_i2c *i2c)
-{
- u32 status;
-
- status = zx2967_i2c_readl(i2c, REG_STAT);
- status |= I2C_IRQ_ACK_CLEAR;
- zx2967_i2c_writel(i2c, status, REG_STAT);
-}
-
-static irqreturn_t zx2967_i2c_isr(int irq, void *dev_id)
-{
- u32 status;
- struct zx2967_i2c *i2c = (struct zx2967_i2c *)dev_id;
-
- status = zx2967_i2c_readl(i2c, REG_STAT) & I2C_INT_MASK;
- zx2967_i2c_isr_clr(i2c);
-
- if (status & I2C_SR_EDEVICE)
- i2c->error = -ENXIO;
- else if (status & I2C_SR_EDATA)
- i2c->error = -EIO;
- else if (status & I2C_TRANS_DONE)
- i2c->error = 0;
- else
- goto done;
-
- complete(&i2c->complete);
-done:
- return IRQ_HANDLED;
-}
-
-static void zx2967_set_addr(struct zx2967_i2c *i2c, u16 addr)
-{
- u16 val;
-
- val = (addr >> I2C_ADDR_LOW_SHIFT) & I2C_ADDR_LOW_MASK;
- zx2967_i2c_writel(i2c, val, REG_DEVADDR_L);
-
- val = (addr >> I2C_ADDR_HI_SHIFT) & I2C_ADDR_HI_MASK;
- zx2967_i2c_writel(i2c, val, REG_DEVADDR_H);
- if (val)
- val = zx2967_i2c_readl(i2c, REG_CMD) | I2C_ADDR_MODE_TEN;
- else
- val = zx2967_i2c_readl(i2c, REG_CMD) & ~I2C_ADDR_MODE_TEN;
- zx2967_i2c_writel(i2c, val, REG_CMD);
-}
-
-static int zx2967_i2c_xfer_bytes(struct zx2967_i2c *i2c, u32 bytes)
-{
- unsigned long time_left;
- int rd = i2c->msg_rd;
- int ret;
-
- reinit_completion(&i2c->complete);
-
- if (rd) {
- zx2967_i2c_writel(i2c, bytes - 1, REG_RDCONF);
- } else {
- ret = zx2967_i2c_fill_tx_fifo(i2c);
- if (ret)
- return ret;
- }
-
- zx2967_i2c_start_ctrl(i2c);
-
- time_left = wait_for_completion_timeout(&i2c->complete,
- I2C_TIMEOUT);
- if (time_left == 0)
- return -ETIMEDOUT;
-
- if (i2c->error)
- return i2c->error;
-
- return rd ? zx2967_i2c_empty_rx_fifo(i2c, bytes) : 0;
-}
-
-static int zx2967_i2c_xfer_msg(struct zx2967_i2c *i2c,
- struct i2c_msg *msg)
-{
- int ret;
- int i;
-
- zx2967_i2c_flush_fifos(i2c);
-
- i2c->cur_trans = msg->buf;
- i2c->residue = msg->len;
- i2c->access_cnt = msg->len / I2C_FIFO_MAX;
- i2c->msg_rd = msg->flags & I2C_M_RD;
-
- for (i = 0; i < i2c->access_cnt; i++) {
- ret = zx2967_i2c_xfer_bytes(i2c, I2C_FIFO_MAX);
- if (ret)
- return ret;
- }
-
- if (i2c->residue > 0) {
- ret = zx2967_i2c_xfer_bytes(i2c, i2c->residue);
- if (ret)
- return ret;
- }
-
- i2c->residue = 0;
- i2c->access_cnt = 0;
-
- return 0;
-}
-
-static int zx2967_i2c_xfer(struct i2c_adapter *adap,
- struct i2c_msg *msgs, int num)
-{
- struct zx2967_i2c *i2c = i2c_get_adapdata(adap);
- int ret;
- int i;
-
- zx2967_set_addr(i2c, msgs->addr);
-
- for (i = 0; i < num; i++) {
- ret = zx2967_i2c_xfer_msg(i2c, &msgs[i]);
- if (ret)
- return ret;
- }
-
- return num;
-}
-
-static void
-zx2967_smbus_xfer_prepare(struct zx2967_i2c *i2c, u16 addr,
- char read_write, u8 command, int size,
- union i2c_smbus_data *data)
-{
- u32 val;
-
- val = zx2967_i2c_readl(i2c, REG_RDCONF);
- val |= I2C_RFIFO_RESET;
- zx2967_i2c_writel(i2c, val, REG_RDCONF);
- zx2967_set_addr(i2c, addr);
- val = zx2967_i2c_readl(i2c, REG_CMD);
- val &= ~I2C_RW_READ;
- zx2967_i2c_writel(i2c, val, REG_CMD);
-
- switch (size) {
- case I2C_SMBUS_BYTE:
- zx2967_i2c_writel(i2c, command, REG_DATA);
- break;
- case I2C_SMBUS_BYTE_DATA:
- zx2967_i2c_writel(i2c, command, REG_DATA);
- if (read_write == I2C_SMBUS_WRITE)
- zx2967_i2c_writel(i2c, data->byte, REG_DATA);
- break;
- case I2C_SMBUS_WORD_DATA:
- zx2967_i2c_writel(i2c, command, REG_DATA);
- if (read_write == I2C_SMBUS_WRITE) {
- zx2967_i2c_writel(i2c, (data->word >> 8), REG_DATA);
- zx2967_i2c_writel(i2c, (data->word & 0xff),
- REG_DATA);
- }
- break;
- }
-}
-
-static int zx2967_smbus_xfer_read(struct zx2967_i2c *i2c, int size,
- union i2c_smbus_data *data)
-{
- unsigned long time_left;
- u8 buf[2];
- u32 val;
-
- reinit_completion(&i2c->complete);
-
- val = zx2967_i2c_readl(i2c, REG_CMD);
- val |= I2C_CMB_RW_EN;
- zx2967_i2c_writel(i2c, val, REG_CMD);
-
- val = zx2967_i2c_readl(i2c, REG_CMD);
- val |= I2C_START;
- zx2967_i2c_writel(i2c, val, REG_CMD);
-
- time_left = wait_for_completion_timeout(&i2c->complete,
- I2C_TIMEOUT);
- if (time_left == 0)
- return -ETIMEDOUT;
-
- if (i2c->error)
- return i2c->error;
-
- switch (size) {
- case I2C_SMBUS_BYTE:
- case I2C_SMBUS_BYTE_DATA:
- val = zx2967_i2c_readl(i2c, REG_DATA);
- data->byte = val;
- break;
- case I2C_SMBUS_WORD_DATA:
- case I2C_SMBUS_PROC_CALL:
- buf[0] = zx2967_i2c_readl(i2c, REG_DATA);
- buf[1] = zx2967_i2c_readl(i2c, REG_DATA);
- data->word = (buf[0] << 8) | buf[1];
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return 0;
-}
-
-static int zx2967_smbus_xfer_write(struct zx2967_i2c *i2c)
-{
- unsigned long time_left;
- u32 val;
-
- reinit_completion(&i2c->complete);
- val = zx2967_i2c_readl(i2c, REG_CMD);
- val |= I2C_START;
- zx2967_i2c_writel(i2c, val, REG_CMD);
-
- time_left = wait_for_completion_timeout(&i2c->complete,
- I2C_TIMEOUT);
- if (time_left == 0)
- return -ETIMEDOUT;
-
- if (i2c->error)
- return i2c->error;
-
- return 0;
-}
-
-static int zx2967_smbus_xfer(struct i2c_adapter *adap, u16 addr,
- unsigned short flags, char read_write,
- u8 command, int size, union i2c_smbus_data *data)
-{
- struct zx2967_i2c *i2c = i2c_get_adapdata(adap);
-
- if (size == I2C_SMBUS_QUICK)
- read_write = I2C_SMBUS_WRITE;
-
- switch (size) {
- case I2C_SMBUS_QUICK:
- case I2C_SMBUS_BYTE:
- case I2C_SMBUS_BYTE_DATA:
- case I2C_SMBUS_WORD_DATA:
- zx2967_smbus_xfer_prepare(i2c, addr, read_write,
- command, size, data);
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- if (read_write == I2C_SMBUS_READ)
- return zx2967_smbus_xfer_read(i2c, size, data);
-
- return zx2967_smbus_xfer_write(i2c);
-}
-
-static u32 zx2967_i2c_func(struct i2c_adapter *adap)
-{
- return I2C_FUNC_I2C |
- I2C_FUNC_SMBUS_QUICK |
- I2C_FUNC_SMBUS_BYTE |
- I2C_FUNC_SMBUS_BYTE_DATA |
- I2C_FUNC_SMBUS_WORD_DATA |
- I2C_FUNC_SMBUS_BLOCK_DATA |
- I2C_FUNC_SMBUS_PROC_CALL |
- I2C_FUNC_SMBUS_I2C_BLOCK;
-}
-
-static int __maybe_unused zx2967_i2c_suspend(struct device *dev)
-{
- struct zx2967_i2c *i2c = dev_get_drvdata(dev);
-
- i2c_mark_adapter_suspended(&i2c->adap);
- clk_disable_unprepare(i2c->clk);
-
- return 0;
-}
-
-static int __maybe_unused zx2967_i2c_resume(struct device *dev)
-{
- struct zx2967_i2c *i2c = dev_get_drvdata(dev);
-
- clk_prepare_enable(i2c->clk);
- i2c_mark_adapter_resumed(&i2c->adap);
-
- return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(zx2967_i2c_dev_pm_ops,
- zx2967_i2c_suspend, zx2967_i2c_resume);
-
-static const struct i2c_algorithm zx2967_i2c_algo = {
- .master_xfer = zx2967_i2c_xfer,
- .smbus_xfer = zx2967_smbus_xfer,
- .functionality = zx2967_i2c_func,
-};
-
-static const struct i2c_adapter_quirks zx2967_i2c_quirks = {
- .flags = I2C_AQ_NO_ZERO_LEN,
-};
-
-static const struct of_device_id zx2967_i2c_of_match[] = {
- { .compatible = "zte,zx296718-i2c", },
- { },
-};
-MODULE_DEVICE_TABLE(of, zx2967_i2c_of_match);
-
-static int zx2967_i2c_probe(struct platform_device *pdev)
-{
- struct zx2967_i2c *i2c;
- void __iomem *reg_base;
- struct clk *clk;
- int ret;
-
- i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
- if (!i2c)
- return -ENOMEM;
-
- reg_base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(reg_base))
- return PTR_ERR(reg_base);
-
- clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(clk)) {
- dev_err(&pdev->dev, "missing controller clock");
- return PTR_ERR(clk);
- }
-
- ret = clk_prepare_enable(clk);
- if (ret) {
- dev_err(&pdev->dev, "failed to enable i2c_clk\n");
- return ret;
- }
-
- ret = device_property_read_u32(&pdev->dev, "clock-frequency",
- &i2c->clk_freq);
- if (ret) {
- dev_err(&pdev->dev, "missing clock-frequency");
- return ret;
- }
-
- ret = platform_get_irq(pdev, 0);
- if (ret < 0)
- return ret;
-
- i2c->irq = ret;
- i2c->reg_base = reg_base;
- i2c->clk = clk;
-
- init_completion(&i2c->complete);
- platform_set_drvdata(pdev, i2c);
-
- ret = zx2967_i2c_reset_hardware(i2c);
- if (ret) {
- dev_err(&pdev->dev, "failed to initialize i2c controller\n");
- goto err_clk_unprepare;
- }
-
- ret = devm_request_irq(&pdev->dev, i2c->irq,
- zx2967_i2c_isr, 0, dev_name(&pdev->dev), i2c);
- if (ret) {
- dev_err(&pdev->dev, "failed to request irq %i\n", i2c->irq);
- goto err_clk_unprepare;
- }
-
- i2c_set_adapdata(&i2c->adap, i2c);
- strlcpy(i2c->adap.name, "zx2967 i2c adapter",
- sizeof(i2c->adap.name));
- i2c->adap.algo = &zx2967_i2c_algo;
- i2c->adap.quirks = &zx2967_i2c_quirks;
- i2c->adap.nr = pdev->id;
- i2c->adap.dev.parent = &pdev->dev;
- i2c->adap.dev.of_node = pdev->dev.of_node;
-
- ret = i2c_add_numbered_adapter(&i2c->adap);
- if (ret)
- goto err_clk_unprepare;
-
- return 0;
-
-err_clk_unprepare:
- clk_disable_unprepare(i2c->clk);
- return ret;
-}
-
-static int zx2967_i2c_remove(struct platform_device *pdev)
-{
- struct zx2967_i2c *i2c = platform_get_drvdata(pdev);
-
- i2c_del_adapter(&i2c->adap);
- clk_disable_unprepare(i2c->clk);
-
- return 0;
-}
-
-static struct platform_driver zx2967_i2c_driver = {
- .probe = zx2967_i2c_probe,
- .remove = zx2967_i2c_remove,
- .driver = {
- .name = "zx2967_i2c",
- .of_match_table = zx2967_i2c_of_match,
- .pm = &zx2967_i2c_dev_pm_ops,
- },
-};
-module_platform_driver(zx2967_i2c_driver);
-
-MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>");
-MODULE_DESCRIPTION("ZTE ZX2967 I2C Bus Controller driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index 37c510d9347a..8ceaa88dd78f 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -225,12 +225,8 @@ static void i2c_acpi_register_device(struct i2c_adapter *adapter,
adev->power.flags.ignore_parent = true;
acpi_device_set_enumerated(adev);
- if (IS_ERR(i2c_new_client_device(adapter, info))) {
+ if (IS_ERR(i2c_new_client_device(adapter, info)))
adev->power.flags.ignore_parent = false;
- dev_err(&adapter->dev,
- "failed to add I2C device %s from ACPI\n",
- dev_name(&adev->dev));
- }
}
static acpi_status i2c_acpi_add_device(acpi_handle handle, u32 level,
diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c
index f5c9787992e9..d2d32c0fd8c3 100644
--- a/drivers/i2c/i2c-core-smbus.c
+++ b/drivers/i2c/i2c-core-smbus.c
@@ -323,8 +323,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
*/
unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];
unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];
- int num = read_write == I2C_SMBUS_READ ? 2 : 1;
- int i;
+ int nmsgs = read_write == I2C_SMBUS_READ ? 2 : 1;
u8 partial_pec = 0;
int status;
struct i2c_msg msg[2] = {
@@ -340,6 +339,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
.buf = msgbuf1,
},
};
+ bool wants_pec = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK
+ && size != I2C_SMBUS_I2C_BLOCK_DATA);
msgbuf0[0] = command;
switch (size) {
@@ -348,13 +349,13 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
/* Special case: The read/write field is used as data */
msg[0].flags = flags | (read_write == I2C_SMBUS_READ ?
I2C_M_RD : 0);
- num = 1;
+ nmsgs = 1;
break;
case I2C_SMBUS_BYTE:
if (read_write == I2C_SMBUS_READ) {
/* Special case: only a read! */
msg[0].flags = I2C_M_RD | flags;
- num = 1;
+ nmsgs = 1;
}
break;
case I2C_SMBUS_BYTE_DATA:
@@ -375,7 +376,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
}
break;
case I2C_SMBUS_PROC_CALL:
- num = 2; /* Special case */
+ nmsgs = 2; /* Special case */
read_write = I2C_SMBUS_READ;
msg[0].len = 3;
msg[1].len = 2;
@@ -398,12 +399,11 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
}
i2c_smbus_try_get_dmabuf(&msg[0], command);
- for (i = 1; i < msg[0].len; i++)
- msg[0].buf[i] = data->block[i - 1];
+ memcpy(msg[0].buf + 1, data->block, msg[0].len - 1);
}
break;
case I2C_SMBUS_BLOCK_PROC_CALL:
- num = 2; /* Another special case */
+ nmsgs = 2; /* Another special case */
read_write = I2C_SMBUS_READ;
if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
dev_err(&adapter->dev,
@@ -414,8 +414,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
msg[0].len = data->block[0] + 2;
i2c_smbus_try_get_dmabuf(&msg[0], command);
- for (i = 1; i < msg[0].len; i++)
- msg[0].buf[i] = data->block[i - 1];
+ memcpy(msg[0].buf + 1, data->block, msg[0].len - 1);
msg[1].flags |= I2C_M_RECV_LEN;
msg[1].len = 1; /* block length will be added by
@@ -437,8 +436,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
msg[0].len = data->block[0] + 1;
i2c_smbus_try_get_dmabuf(&msg[0], command);
- for (i = 1; i <= data->block[0]; i++)
- msg[0].buf[i] = data->block[i];
+ memcpy(msg[0].buf + 1, data->block + 1, data->block[0]);
}
break;
default:
@@ -446,33 +444,31 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
return -EOPNOTSUPP;
}
- i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK
- && size != I2C_SMBUS_I2C_BLOCK_DATA);
- if (i) {
+ if (wants_pec) {
/* Compute PEC if first message is a write */
if (!(msg[0].flags & I2C_M_RD)) {
- if (num == 1) /* Write only */
+ if (nmsgs == 1) /* Write only */
i2c_smbus_add_pec(&msg[0]);
else /* Write followed by read */
partial_pec = i2c_smbus_msg_pec(0, &msg[0]);
}
/* Ask for PEC if last message is a read */
- if (msg[num-1].flags & I2C_M_RD)
- msg[num-1].len++;
+ if (msg[nmsgs - 1].flags & I2C_M_RD)
+ msg[nmsgs - 1].len++;
}
- status = __i2c_transfer(adapter, msg, num);
+ status = __i2c_transfer(adapter, msg, nmsgs);
if (status < 0)
goto cleanup;
- if (status != num) {
+ if (status != nmsgs) {
status = -EIO;
goto cleanup;
}
status = 0;
/* Check PEC if last message is a read */
- if (i && (msg[num-1].flags & I2C_M_RD)) {
- status = i2c_smbus_check_pec(partial_pec, &msg[num-1]);
+ if (wants_pec && (msg[nmsgs - 1].flags & I2C_M_RD)) {
+ status = i2c_smbus_check_pec(partial_pec, &msg[nmsgs - 1]);
if (status < 0)
goto cleanup;
}
@@ -490,8 +486,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
data->word = msgbuf1[0] | (msgbuf1[1] << 8);
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
- for (i = 0; i < data->block[0]; i++)
- data->block[i + 1] = msg[1].buf[i];
+ memcpy(data->block + 1, msg[1].buf, data->block[0]);
break;
case I2C_SMBUS_BLOCK_DATA:
case I2C_SMBUS_BLOCK_PROC_CALL:
@@ -502,8 +497,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
status = -EPROTO;
goto cleanup;
}
- for (i = 0; i < msg[1].buf[0] + 1; i++)
- data->block[i] = msg[1].buf[i];
+ memcpy(data->block, msg[1].buf, msg[1].buf[0] + 1);
break;
}
diff --git a/drivers/i2c/i2c-slave-testunit.c b/drivers/i2c/i2c-slave-testunit.c
index c288102de324..56dae08dfd48 100644
--- a/drivers/i2c/i2c-slave-testunit.c
+++ b/drivers/i2c/i2c-slave-testunit.c
@@ -19,6 +19,7 @@
enum testunit_cmds {
TU_CMD_READ_BYTES = 1, /* save 0 for ABORT, RESET or similar */
TU_CMD_HOST_NOTIFY,
+ TU_CMD_SMBUS_BLOCK_PROC_CALL,
TU_NUM_CMDS
};
@@ -88,6 +89,8 @@ static int i2c_slave_testunit_slave_cb(struct i2c_client *client,
enum i2c_slave_event event, u8 *val)
{
struct testunit_data *tu = i2c_get_clientdata(client);
+ bool is_proc_call = tu->reg_idx == 3 && tu->regs[TU_REG_DATAL] == 1 &&
+ tu->regs[TU_REG_CMD] == TU_CMD_SMBUS_BLOCK_PROC_CALL;
int ret = 0;
switch (event) {
@@ -118,12 +121,17 @@ static int i2c_slave_testunit_slave_cb(struct i2c_client *client,
fallthrough;
case I2C_SLAVE_WRITE_REQUESTED:
+ memset(tu->regs, 0, TU_NUM_REGS);
tu->reg_idx = 0;
break;
- case I2C_SLAVE_READ_REQUESTED:
case I2C_SLAVE_READ_PROCESSED:
- *val = TU_CUR_VERSION;
+ if (is_proc_call && tu->regs[TU_REG_DATAH])
+ tu->regs[TU_REG_DATAH]--;
+ fallthrough;
+
+ case I2C_SLAVE_READ_REQUESTED:
+ *val = is_proc_call ? tu->regs[TU_REG_DATAH] : TU_CUR_VERSION;
break;
}
diff --git a/drivers/i2c/i2c-stub.c b/drivers/i2c/i2c-stub.c
index 537a598e22db..d642cad219d9 100644
--- a/drivers/i2c/i2c-stub.c
+++ b/drivers/i2c/i2c-stub.c
@@ -7,7 +7,6 @@
*/
-#define DEBUG 1
#define pr_fmt(fmt) "i2c-stub: " fmt
#include <linux/errno.h>
diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index 4effe563e9e8..bac415a52b78 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -49,60 +49,112 @@ static int i2c_mux_gpio_deselect(struct i2c_mux_core *muxc, u32 chan)
return 0;
}
-#ifdef CONFIG_OF
-static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
- struct platform_device *pdev)
+#ifdef CONFIG_ACPI
+
+static int i2c_mux_gpio_get_acpi_adr(struct device *dev,
+ struct fwnode_handle *fwdev,
+ unsigned int *adr)
+
+{
+ unsigned long long adr64;
+ acpi_status status;
+
+ status = acpi_evaluate_integer(ACPI_HANDLE_FWNODE(fwdev),
+ METHOD_NAME__ADR,
+ NULL, &adr64);
+
+ if (!ACPI_SUCCESS(status)) {
+ dev_err(dev, "Cannot get address\n");
+ return -EINVAL;
+ }
+
+ *adr = adr64;
+ if (*adr != adr64) {
+ dev_err(dev, "Address out of range\n");
+ return -ERANGE;
+ }
+
+ return 0;
+}
+
+#else
+
+static int i2c_mux_gpio_get_acpi_adr(struct device *dev,
+ struct fwnode_handle *fwdev,
+ unsigned int *adr)
+{
+ return -EINVAL;
+}
+
+#endif
+
+static int i2c_mux_gpio_probe_fw(struct gpiomux *mux,
+ struct platform_device *pdev)
{
- struct device_node *np = pdev->dev.of_node;
- struct device_node *adapter_np, *child;
- struct i2c_adapter *adapter;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct device_node *adapter_np;
+ struct i2c_adapter *adapter = NULL;
+ struct fwnode_handle *child;
unsigned *values;
- int i = 0;
+ int rc, i = 0;
+
+ if (is_of_node(dev->fwnode)) {
+ if (!np)
+ return -ENODEV;
- if (!np)
- return -ENODEV;
+ adapter_np = of_parse_phandle(np, "i2c-parent", 0);
+ if (!adapter_np) {
+ dev_err(&pdev->dev, "Cannot parse i2c-parent\n");
+ return -ENODEV;
+ }
+ adapter = of_find_i2c_adapter_by_node(adapter_np);
+ of_node_put(adapter_np);
+
+ } else if (is_acpi_node(dev->fwnode)) {
+ /*
+ * In ACPI land the mux should be a direct child of the i2c
+ * bus it muxes.
+ */
+ acpi_handle dev_handle = ACPI_HANDLE(dev->parent);
- adapter_np = of_parse_phandle(np, "i2c-parent", 0);
- if (!adapter_np) {
- dev_err(&pdev->dev, "Cannot parse i2c-parent\n");
- return -ENODEV;
+ adapter = i2c_acpi_find_adapter_by_handle(dev_handle);
}
- adapter = of_find_i2c_adapter_by_node(adapter_np);
- of_node_put(adapter_np);
+
if (!adapter)
return -EPROBE_DEFER;
mux->data.parent = i2c_adapter_id(adapter);
put_device(&adapter->dev);
- mux->data.n_values = of_get_child_count(np);
-
- values = devm_kcalloc(&pdev->dev,
+ mux->data.n_values = device_get_child_node_count(dev);
+ values = devm_kcalloc(dev,
mux->data.n_values, sizeof(*mux->data.values),
GFP_KERNEL);
if (!values) {
- dev_err(&pdev->dev, "Cannot allocate values array");
+ dev_err(dev, "Cannot allocate values array");
return -ENOMEM;
}
- for_each_child_of_node(np, child) {
- of_property_read_u32(child, "reg", values + i);
+ device_for_each_child_node(dev, child) {
+ if (is_of_node(child)) {
+ fwnode_property_read_u32(child, "reg", values + i);
+
+ } else if (is_acpi_node(child)) {
+ rc = i2c_mux_gpio_get_acpi_adr(dev, child, values + i);
+ if (rc)
+ return rc;
+ }
+
i++;
}
mux->data.values = values;
- if (of_property_read_u32(np, "idle-state", &mux->data.idle))
+ if (fwnode_property_read_u32(dev->fwnode, "idle-state", &mux->data.idle))
mux->data.idle = I2C_MUX_GPIO_NO_IDLE;
return 0;
}
-#else
-static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
- struct platform_device *pdev)
-{
- return 0;
-}
-#endif
static int i2c_mux_gpio_probe(struct platform_device *pdev)
{
@@ -118,7 +170,7 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev)
return -ENOMEM;
if (!dev_get_platdata(&pdev->dev)) {
- ret = i2c_mux_gpio_probe_dt(mux, pdev);
+ ret = i2c_mux_gpio_probe_fw(mux, pdev);
if (ret < 0)
return ret;
} else {
diff --git a/drivers/i2c/muxes/i2c-mux-mlxcpld.c b/drivers/i2c/muxes/i2c-mux-mlxcpld.c
index 5ed55ca4fe93..1a879f6a31ef 100644
--- a/drivers/i2c/muxes/i2c-mux-mlxcpld.c
+++ b/drivers/i2c/muxes/i2c-mux-mlxcpld.c
@@ -1,35 +1,8 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
/*
- * drivers/i2c/muxes/i2c-mux-mlxcpld.c
- * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2016 Michael Shych <michaels@mellanox.com>
+ * Mellanox i2c mux driver
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the names of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * Copyright (C) 2016-2020 Mellanox Technologies
*/
#include <linux/device.h>
@@ -38,19 +11,19 @@
#include <linux/io.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/platform_data/x86/mlxcpld.h>
+#include <linux/platform_data/mlxcpld.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
-#define CPLD_MUX_MAX_NCHANS 8
-
/* mlxcpld_mux - mux control structure:
- * @last_chan - last register value
+ * @last_val - last selected register value or -1 if mux deselected
* @client - I2C device client
+ * @pdata: platform data
*/
struct mlxcpld_mux {
- u8 last_chan;
+ int last_val;
struct i2c_client *client;
+ struct mlxcpld_mux_plat_data pdata;
};
/* MUX logic description.
@@ -81,37 +54,50 @@ struct mlxcpld_mux {
*
*/
-static const struct i2c_device_id mlxcpld_mux_id[] = {
- { "mlxcpld_mux_module", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, mlxcpld_mux_id);
-
/* Write to mux register. Don't use i2c_transfer() and i2c_smbus_xfer()
* for this as they will try to lock adapter a second time.
*/
static int mlxcpld_mux_reg_write(struct i2c_adapter *adap,
- struct i2c_client *client, u8 val)
+ struct mlxcpld_mux *mux, u32 val)
{
- struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&client->dev);
- union i2c_smbus_data data = { .byte = val };
-
- return __i2c_smbus_xfer(adap, client->addr, client->flags,
- I2C_SMBUS_WRITE, pdata->sel_reg_addr,
- I2C_SMBUS_BYTE_DATA, &data);
+ struct i2c_client *client = mux->client;
+ union i2c_smbus_data data;
+ struct i2c_msg msg;
+ u8 buf[3];
+
+ switch (mux->pdata.reg_size) {
+ case 1:
+ data.byte = val;
+ return __i2c_smbus_xfer(adap, client->addr, client->flags,
+ I2C_SMBUS_WRITE, mux->pdata.sel_reg_addr,
+ I2C_SMBUS_BYTE_DATA, &data);
+ case 2:
+ buf[0] = mux->pdata.sel_reg_addr >> 8;
+ buf[1] = mux->pdata.sel_reg_addr;
+ buf[2] = val;
+ msg.addr = client->addr;
+ msg.buf = buf;
+ msg.len = mux->pdata.reg_size + 1;
+ msg.flags = 0;
+ return __i2c_transfer(adap, &msg, 1);
+ default:
+ return -EINVAL;
+ }
}
static int mlxcpld_mux_select_chan(struct i2c_mux_core *muxc, u32 chan)
{
- struct mlxcpld_mux *data = i2c_mux_priv(muxc);
- struct i2c_client *client = data->client;
- u8 regval = chan + 1;
+ struct mlxcpld_mux *mux = i2c_mux_priv(muxc);
+ u32 regval = chan;
int err = 0;
+ if (mux->pdata.reg_size == 1)
+ regval += 1;
+
/* Only select the channel if its different from the last channel */
- if (data->last_chan != regval) {
- err = mlxcpld_mux_reg_write(muxc->parent, client, regval);
- data->last_chan = err < 0 ? 0 : regval;
+ if (mux->last_val != regval) {
+ err = mlxcpld_mux_reg_write(muxc->parent, mux, regval);
+ mux->last_val = err < 0 ? -1 : regval;
}
return err;
@@ -119,56 +105,64 @@ static int mlxcpld_mux_select_chan(struct i2c_mux_core *muxc, u32 chan)
static int mlxcpld_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
{
- struct mlxcpld_mux *data = i2c_mux_priv(muxc);
- struct i2c_client *client = data->client;
+ struct mlxcpld_mux *mux = i2c_mux_priv(muxc);
/* Deselect active channel */
- data->last_chan = 0;
+ mux->last_val = -1;
- return mlxcpld_mux_reg_write(muxc->parent, client, data->last_chan);
+ return mlxcpld_mux_reg_write(muxc->parent, mux, 0);
}
/* Probe/reomove functions */
-static int mlxcpld_mux_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int mlxcpld_mux_probe(struct platform_device *pdev)
{
- struct i2c_adapter *adap = client->adapter;
- struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&client->dev);
+ struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&pdev->dev);
+ struct i2c_client *client = to_i2c_client(pdev->dev.parent);
struct i2c_mux_core *muxc;
- int num, force;
struct mlxcpld_mux *data;
- int err;
+ int num, err;
+ u32 func;
if (!pdata)
return -EINVAL;
- if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+ switch (pdata->reg_size) {
+ case 1:
+ func = I2C_FUNC_SMBUS_WRITE_BYTE_DATA;
+ break;
+ case 2:
+ func = I2C_FUNC_I2C;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (!i2c_check_functionality(client->adapter, func))
return -ENODEV;
- muxc = i2c_mux_alloc(adap, &client->dev, CPLD_MUX_MAX_NCHANS,
+ muxc = i2c_mux_alloc(client->adapter, &pdev->dev, pdata->num_adaps,
sizeof(*data), 0, mlxcpld_mux_select_chan,
mlxcpld_mux_deselect);
if (!muxc)
return -ENOMEM;
+ platform_set_drvdata(pdev, muxc);
data = i2c_mux_priv(muxc);
- i2c_set_clientdata(client, muxc);
data->client = client;
- data->last_chan = 0; /* force the first selection */
+ memcpy(&data->pdata, pdata, sizeof(*pdata));
+ data->last_val = -1; /* force the first selection */
/* Create an adapter for each channel. */
- for (num = 0; num < CPLD_MUX_MAX_NCHANS; num++) {
- if (num >= pdata->num_adaps)
- /* discard unconfigured channels */
- break;
-
- force = pdata->adap_ids[num];
-
- err = i2c_mux_add_adapter(muxc, force, num, 0);
+ for (num = 0; num < pdata->num_adaps; num++) {
+ err = i2c_mux_add_adapter(muxc, 0, pdata->chan_ids[num], 0);
if (err)
goto virt_reg_failed;
}
+ /* Notify caller when all channels' adapters are created. */
+ if (pdata->completion_notify)
+ pdata->completion_notify(pdata->handle, muxc->parent, muxc->adapter);
+
return 0;
virt_reg_failed:
@@ -176,24 +170,23 @@ virt_reg_failed:
return err;
}
-static int mlxcpld_mux_remove(struct i2c_client *client)
+static int mlxcpld_mux_remove(struct platform_device *pdev)
{
- struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+ struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
i2c_mux_del_adapters(muxc);
return 0;
}
-static struct i2c_driver mlxcpld_mux_driver = {
- .driver = {
- .name = "mlxcpld-mux",
+static struct platform_driver mlxcpld_mux_driver = {
+ .driver = {
+ .name = "i2c-mux-mlxcpld",
},
- .probe = mlxcpld_mux_probe,
- .remove = mlxcpld_mux_remove,
- .id_table = mlxcpld_mux_id,
+ .probe = mlxcpld_mux_probe,
+ .remove = mlxcpld_mux_remove,
};
-module_i2c_driver(mlxcpld_mux_driver);
+module_platform_driver(mlxcpld_mux_driver);
MODULE_AUTHOR("Michael Shych (michaels@mellanox.com)");
MODULE_DESCRIPTION("Mellanox I2C-CPLD-MUX driver");
diff --git a/include/linux/platform_data/mlxcpld.h b/include/linux/platform_data/mlxcpld.h
new file mode 100644
index 000000000000..d7610b528856
--- /dev/null
+++ b/include/linux/platform_data/mlxcpld.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+/*
+ * Mellanox I2C multiplexer support in CPLD
+ *
+ * Copyright (C) 2016-2020 Mellanox Technologies
+ */
+
+#ifndef _LINUX_I2C_MLXCPLD_H
+#define _LINUX_I2C_MLXCPLD_H
+
+/* Platform data for the CPLD I2C multiplexers */
+
+/* mlxcpld_mux_plat_data - per mux data, used with i2c_register_board_info
+ * @chan_ids - channels array
+ * @num_adaps - number of adapters
+ * @sel_reg_addr - mux select register offset in CPLD space
+ * @reg_size: register size in bytes
+ * @handle: handle to be passed by callback
+ * @completion_notify: callback to notify when all the adapters are created
+ */
+struct mlxcpld_mux_plat_data {
+ int *chan_ids;
+ int num_adaps;
+ int sel_reg_addr;
+ u8 reg_size;
+ void *handle;
+ int (*completion_notify)(void *handle, struct i2c_adapter *parent,
+ struct i2c_adapter *adapters[]);
+};
+
+#endif /* _LINUX_I2C_MLXCPLD_H */
diff --git a/include/linux/platform_data/x86/mlxcpld.h b/include/linux/platform_data/x86/mlxcpld.h
deleted file mode 100644
index b08dcb183fca..000000000000
--- a/include/linux/platform_data/x86/mlxcpld.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * mlxcpld.h - Mellanox I2C multiplexer support in CPLD
- *
- * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2016 Michael Shych <michaels@mellanox.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the names of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _LINUX_I2C_MLXCPLD_H
-#define _LINUX_I2C_MLXCPLD_H
-
-/* Platform data for the CPLD I2C multiplexers */
-
-/* mlxcpld_mux_plat_data - per mux data, used with i2c_register_board_info
- * @adap_ids - adapter array
- * @num_adaps - number of adapters
- * @sel_reg_addr - mux select register offset in CPLD space
- */
-struct mlxcpld_mux_plat_data {
- int *adap_ids;
- int num_adaps;
- int sel_reg_addr;
-};
-
-#endif /* _LINUX_I2C_MLXCPLD_H */
diff --git a/include/uapi/linux/i2c-dev.h b/include/uapi/linux/i2c-dev.h
index 85f8047afcf2..1c4cec4ddd84 100644
--- a/include/uapi/linux/i2c-dev.h
+++ b/include/uapi/linux/i2c-dev.h
@@ -1,25 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
- i2c-dev.h - i2c-bus driver, char device interface
-
- Copyright (C) 1995-97 Simon G. Vogl
- Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301 USA.
-*/
+ * i2c-dev.h - I2C bus char device interface
+ *
+ * Copyright (C) 1995-97 Simon G. Vogl
+ * Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
+ */
#ifndef _UAPI_LINUX_I2C_DEV_H
#define _UAPI_LINUX_I2C_DEV_H
diff --git a/include/uapi/linux/i2c.h b/include/uapi/linux/i2c.h
index f71a1751cacf..92326ebde350 100644
--- a/include/uapi/linux/i2c.h
+++ b/include/uapi/linux/i2c.h
@@ -1,29 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
-/* ------------------------------------------------------------------------- */
-/* */
-/* i2c.h - definitions for the i2c-bus interface */
-/* */
-/* ------------------------------------------------------------------------- */
-/* Copyright (C) 1995-2000 Simon G. Vogl
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- MA 02110-1301 USA. */
-/* ------------------------------------------------------------------------- */
-
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
- Frodo Looijaard <frodol@dds.nl> */
+/*
+ * i2c.h - definitions for the I2C bus interface
+ *
+ * Copyright (C) 1995-2000 Simon G. Vogl
+ * With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
+ * Frodo Looijaard <frodol@dds.nl>
+ */
#ifndef _UAPI_LINUX_I2C_H
#define _UAPI_LINUX_I2C_H
@@ -32,18 +14,41 @@
/**
* struct i2c_msg - an I2C transaction segment beginning with START
- * @addr: Slave address, either seven or ten bits. When this is a ten
- * bit address, I2C_M_TEN must be set in @flags and the adapter
- * must support I2C_FUNC_10BIT_ADDR.
- * @flags: I2C_M_RD is handled by all adapters. No other flags may be
- * provided unless the adapter exported the relevant I2C_FUNC_*
- * flags through i2c_check_functionality().
- * @len: Number of data bytes in @buf being read from or written to the
- * I2C slave address. For read transactions where I2C_M_RECV_LEN
- * is set, the caller guarantees that this buffer can hold up to
- * 32 bytes in addition to the initial length byte sent by the
- * slave (plus, if used, the SMBus PEC); and this value will be
- * incremented by the number of block data bytes received.
+ *
+ * @addr: Slave address, either 7 or 10 bits. When this is a 10 bit address,
+ * %I2C_M_TEN must be set in @flags and the adapter must support
+ * %I2C_FUNC_10BIT_ADDR.
+ *
+ * @flags:
+ * Supported by all adapters:
+ * %I2C_M_RD: read data (from slave to master). Guaranteed to be 0x0001!
+ *
+ * Optional:
+ * %I2C_M_DMA_SAFE: the buffer of this message is DMA safe. Makes only sense
+ * in kernelspace, because userspace buffers are copied anyway
+ *
+ * Only if I2C_FUNC_10BIT_ADDR is set:
+ * %I2C_M_TEN: this is a 10 bit chip address
+ *
+ * Only if I2C_FUNC_SMBUS_READ_BLOCK_DATA is set:
+ * %I2C_M_RECV_LEN: message length will be first received byte
+ *
+ * Only if I2C_FUNC_NOSTART is set:
+ * %I2C_M_NOSTART: skip repeated start sequence
+
+ * Only if I2C_FUNC_PROTOCOL_MANGLING is set:
+ * %I2C_M_NO_RD_ACK: in a read message, master ACK/NACK bit is skipped
+ * %I2C_M_IGNORE_NAK: treat NACK from client as ACK
+ * %I2C_M_REV_DIR_ADDR: toggles the Rd/Wr bit
+ * %I2C_M_STOP: force a STOP condition after the message
+ *
+ * @len: Number of data bytes in @buf being read from or written to the I2C
+ * slave address. For read transactions where %I2C_M_RECV_LEN is set, the
+ * caller guarantees that this buffer can hold up to %I2C_SMBUS_BLOCK_MAX
+ * bytes in addition to the initial length byte sent by the slave (plus,
+ * if used, the SMBus PEC); and this value will be incremented by the number
+ * of block data bytes received.
+ *
* @buf: The buffer into which data is read, or from which it's written.
*
* An i2c_msg is the low level representation of one segment of an I2C
@@ -60,40 +65,36 @@
* group, it is followed by a STOP. Otherwise it is followed by the next
* @i2c_msg transaction segment, beginning with a (repeated) START.
*
- * Alternatively, when the adapter supports I2C_FUNC_PROTOCOL_MANGLING then
+ * Alternatively, when the adapter supports %I2C_FUNC_PROTOCOL_MANGLING then
* passing certain @flags may have changed those standard protocol behaviors.
* Those flags are only for use with broken/nonconforming slaves, and with
- * adapters which are known to support the specific mangling options they
- * need (one or more of IGNORE_NAK, NO_RD_ACK, NOSTART, and REV_DIR_ADDR).
+ * adapters which are known to support the specific mangling options they need.
*/
struct i2c_msg {
- __u16 addr; /* slave address */
+ __u16 addr;
__u16 flags;
-#define I2C_M_RD 0x0001 /* read data, from slave to master */
- /* I2C_M_RD is guaranteed to be 0x0001! */
-#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */
-#define I2C_M_DMA_SAFE 0x0200 /* the buffer of this message is DMA safe */
- /* makes only sense in kernelspace */
- /* userspace buffers are copied anyway */
-#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
-#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
-#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
-#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
-#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_NOSTART */
-#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */
- __u16 len; /* msg length */
- __u8 *buf; /* pointer to msg data */
+#define I2C_M_RD 0x0001 /* guaranteed to be 0x0001! */
+#define I2C_M_TEN 0x0010 /* use only if I2C_FUNC_10BIT_ADDR */
+#define I2C_M_DMA_SAFE 0x0200 /* use only in kernel space */
+#define I2C_M_RECV_LEN 0x0400 /* use only if I2C_FUNC_SMBUS_READ_BLOCK_DATA */
+#define I2C_M_NO_RD_ACK 0x0800 /* use only if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_IGNORE_NAK 0x1000 /* use only if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_REV_DIR_ADDR 0x2000 /* use only if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_NOSTART 0x4000 /* use only if I2C_FUNC_NOSTART */
+#define I2C_M_STOP 0x8000 /* use only if I2C_FUNC_PROTOCOL_MANGLING */
+ __u16 len;
+ __u8 *buf;
};
/* To determine what functionality is present */
#define I2C_FUNC_I2C 0x00000001
-#define I2C_FUNC_10BIT_ADDR 0x00000002
-#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_IGNORE_NAK etc. */
+#define I2C_FUNC_10BIT_ADDR 0x00000002 /* required for I2C_M_TEN */
+#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* required for I2C_M_IGNORE_NAK etc. */
#define I2C_FUNC_SMBUS_PEC 0x00000008
-#define I2C_FUNC_NOSTART 0x00000010 /* I2C_M_NOSTART */
+#define I2C_FUNC_NOSTART 0x00000010 /* required for I2C_M_NOSTART */
#define I2C_FUNC_SLAVE 0x00000020
-#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */
+#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 or later */
#define I2C_FUNC_SMBUS_QUICK 0x00010000
#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
@@ -102,11 +103,11 @@ struct i2c_msg {
#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000
#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000
#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000
-#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000
+#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000 /* required for I2C_M_RECV_LEN */
#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */
-#define I2C_FUNC_SMBUS_HOST_NOTIFY 0x10000000
+#define I2C_FUNC_SMBUS_HOST_NOTIFY 0x10000000 /* SMBus 2.0 or later */
#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
I2C_FUNC_SMBUS_WRITE_BYTE)
@@ -128,6 +129,11 @@ struct i2c_msg {
I2C_FUNC_SMBUS_I2C_BLOCK | \
I2C_FUNC_SMBUS_PEC)
+/* if I2C_M_RECV_LEN is also supported */
+#define I2C_FUNC_SMBUS_EMUL_ALL (I2C_FUNC_SMBUS_EMUL | \
+ I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
+ I2C_FUNC_SMBUS_BLOCK_PROC_CALL)
+
/*
* Data for SMBus Messages
*/