Merge branch 'i2c/for-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 14 Jun 2018 07:21:46 +0000 (16:21 +0900)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 14 Jun 2018 07:21:46 +0000 (16:21 +0900)
Pull i2c updates from Wolfram Sang:

 - mainly feature additions to drivers (stm32f7, qup, xlp9xx, mlxcpld, ...)

 - conversion to use the i2c_8bit_addr_from_msg macro consistently

 - move includes to platform_data

 - core updates to allow the (still in review) I3C subsystem to connect

 - and the regular share of smaller driver updates

* 'i2c/for-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (68 commits)
  i2c: qup: fix building without CONFIG_ACPI
  i2c: tegra: Remove suspend-resume
  i2c: imx-lpi2c: Switch to SPDX identifier
  i2c: mxs: Switch to SPDX identifier
  i2c: busses: make use of i2c_8bit_addr_from_msg
  i2c: algos: make use of i2c_8bit_addr_from_msg
  i2c: rcar: document R8A77980 bindings
  i2c: qup: Add command-line parameter to override SCL frequency
  i2c: qup: Correct duty cycle for FM and FM+
  i2c: qup: Add support for Fast Mode Plus
  i2c: qup: add probe path for Centriq ACPI devices
  i2c: robotfuzz-osif: drop pointless test
  i2c: robotfuzz-osif: remove pointless local variable
  i2c: rk3x: Don't print visible virtual mapping MMIO address
  i2c: opal: don't check number of messages in the driver
  i2c: ibm_iic: don't check number of messages in the driver
  i2c: imx: Switch to SPDX identifier
  i2c: mux: pca954x: merge calls to of_match_device and of_device_get_match_data
  i2c: mux: demux-pinctrl: use proper parent device for demux adapter
  i2c: mux: improve error message for failed symlink
  ...

94 files changed:
Documentation/devicetree/bindings/i2c/i2c-davinci.txt
Documentation/devicetree/bindings/i2c/i2c-rcar.txt
Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt
Documentation/i2c/busses/i2c-mlxcpld
Documentation/i2c/busses/i2c-ocores
Documentation/i2c/muxes/i2c-mux-gpio
MAINTAINERS
arch/arm/mach-ks8695/board-acs5k.c
arch/arm/mach-omap1/board-htcherald.c
arch/arm/mach-omap1/common.h
arch/arm/mach-omap1/i2c.c
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/omap_hwmod_2420_data.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_33xx_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_hwmod_54xx_data.c
arch/arm/mach-omap2/omap_hwmod_7xx_data.c
arch/arm/mach-pxa/palmz72.c
arch/arm/mach-pxa/viper.c
arch/arm/mach-sa1100/simpad.c
arch/mips/alchemy/board-gpr.c
arch/sh/boards/board-sh7785lcr.c
drivers/i2c/algos/i2c-algo-bit.c
drivers/i2c/algos/i2c-algo-pca.c
drivers/i2c/algos/i2c-algo-pcf.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-aspeed.c
drivers/i2c/busses/i2c-at91.c
drivers/i2c/busses/i2c-axxia.c
drivers/i2c/busses/i2c-designware-common.c
drivers/i2c/busses/i2c-designware-core.h
drivers/i2c/busses/i2c-designware-master.c
drivers/i2c/busses/i2c-designware-slave.c
drivers/i2c/busses/i2c-diolan-u2c.c
drivers/i2c/busses/i2c-efm32.c
drivers/i2c/busses/i2c-eg20t.c
drivers/i2c/busses/i2c-emev2.c
drivers/i2c/busses/i2c-exynos5.c
drivers/i2c/busses/i2c-gpio.c
drivers/i2c/busses/i2c-hix5hd2.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-ibm_iic.c
drivers/i2c/busses/i2c-imx-lpi2c.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-kempld.c
drivers/i2c/busses/i2c-mlxcpld.c
drivers/i2c/busses/i2c-mt65xx.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-nomadik.c
drivers/i2c/busses/i2c-ocores.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-opal.c
drivers/i2c/busses/i2c-pasemi.c
drivers/i2c/busses/i2c-pca-platform.c
drivers/i2c/busses/i2c-pnx.c
drivers/i2c/busses/i2c-qup.c
drivers/i2c/busses/i2c-rcar.c
drivers/i2c/busses/i2c-riic.c
drivers/i2c/busses/i2c-rk3x.c
drivers/i2c/busses/i2c-robotfuzz-osif.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-sh_mobile.c
drivers/i2c/busses/i2c-stm32.c [new file with mode: 0644]
drivers/i2c/busses/i2c-stm32.h
drivers/i2c/busses/i2c-stm32f7.c
drivers/i2c/busses/i2c-stu300.c
drivers/i2c/busses/i2c-synquacer.c
drivers/i2c/busses/i2c-tegra.c
drivers/i2c/busses/i2c-xiic.c
drivers/i2c/busses/i2c-xlp9xx.c
drivers/i2c/i2c-core-base.c
drivers/i2c/i2c-core-of.c
drivers/i2c/i2c-core-smbus.c
drivers/i2c/i2c-mux.c
drivers/i2c/muxes/i2c-demux-pinctrl.c
drivers/i2c/muxes/i2c-mux-gpio.c
drivers/i2c/muxes/i2c-mux-ltc4306.c
drivers/i2c/muxes/i2c-mux-pca954x.c
drivers/i2c/muxes/i2c-mux-reg.c
drivers/media/platform/marvell-ccic/mmp-driver.c
drivers/mfd/sm501.c
drivers/mfd/timberdale.c
drivers/misc/eeprom/at24.c
include/linux/i2c-pnx.h [deleted file]
include/linux/i2c.h
include/linux/platform_data/i2c-gpio.h [moved from include/linux/i2c-gpio.h with 100% similarity]
include/linux/platform_data/i2c-mux-gpio.h [moved from include/linux/i2c-mux-gpio.h with 100% similarity]
include/linux/platform_data/i2c-ocores.h [moved from include/linux/i2c-ocores.h with 100% similarity]
include/linux/platform_data/i2c-omap.h [moved from include/linux/i2c-omap.h with 100% similarity]
include/linux/platform_data/i2c-pca-platform.h [moved from include/linux/i2c-pca-platform.h with 100% similarity]
include/linux/platform_data/i2c-xiic.h [moved from include/linux/i2c-xiic.h with 100% similarity]

index 64e6e65..b745f37 100644 (file)
@@ -24,7 +24,7 @@ Recommended properties :
 - clock-frequency : desired I2C bus clock frequency in Hz.
 - ti,has-pfunc: boolean; if defined, it indicates that SoC supports PFUNC
        registers. PFUNC registers allow to switch I2C pins to function as
-       GPIOs, so they can by toggled manually.
+       GPIOs, so they can be toggled manually.
 
 Example (enbw_cmc board):
        i2c@1c22000 {
index 4a7811e..7ce8fae 100644 (file)
@@ -15,6 +15,7 @@ Required properties:
        "renesas,i2c-r8a7796" if the device is a part of a R8A7796 SoC.
        "renesas,i2c-r8a77965" if the device is a part of a R8A77965 SoC.
        "renesas,i2c-r8a77970" if the device is a part of a R8A77970 SoC.
+       "renesas,i2c-r8a77980" if the device is a part of a R8A77980 SoC.
        "renesas,i2c-r8a77995" if the device is a part of a R8A77995 SoC.
        "renesas,rcar-gen1-i2c" for a generic R-Car Gen1 compatible device.
        "renesas,rcar-gen2-i2c" for a generic R-Car Gen2 or RZ/G1 compatible
index 89b3250..66ae46d 100644 (file)
@@ -8,9 +8,7 @@ Required properties:
       (b) "samsung, s3c2440-i2c", for i2c compatible with s3c2440 i2c.
       (c) "samsung, s3c2440-hdmiphy-i2c", for s3c2440-like i2c used
           inside HDMIPHY block found on several samsung SoCs
-      (d) "samsung, exynos5440-i2c", for s3c2440-like i2c used
-          on EXYNOS5440 which does not need GPIO configuration.
-      (e) "samsung, exynos5-sata-phy-i2c", for s3c2440-like i2c used as
+      (d) "samsung, exynos5-sata-phy-i2c", for s3c2440-like i2c used as
           a host to SATA PHY controller on an internal bus.
   - reg: physical base address of the controller and length of memory mapped
     region.
index 4e46c44..925904a 100644 (file)
@@ -20,6 +20,10 @@ The next transaction types are supported:
  - Write Byte/Block.
 
 Registers:
+CPBLTY         0x0 - capability reg.
+                       Bits [6:5] - transaction length. b01 - 72B is supported,
+                       36B in other case.
+                       Bit 7 - SMBus block read support.
 CTRL           0x1 - control reg.
                        Resets all the registers.
 HALF_CYC       0x4 - cycle reg.
index 9e1dfe7..4e713f4 100644 (file)
@@ -18,7 +18,7 @@ Usage
 i2c-ocores uses the platform bus, so you need to provide a struct
 platform_device with the base address and interrupt number. The
 dev.platform_data of the device should also point to a struct
-ocores_i2c_platform_data (see linux/i2c-ocores.h) describing the
+ocores_i2c_platform_data (see linux/platform_data/i2c-ocores.h) describing the
 distance between registers and the input clock speed.
 There is also a possibility to attach a list of i2c_board_info which
 the i2c-ocores driver will add to the bus upon creation.
index 7a8d7d2..893ecdf 100644 (file)
@@ -30,12 +30,12 @@ i2c-mux-gpio uses the platform bus, so you need to provide a struct
 platform_device with the platform_data pointing to a struct
 i2c_mux_gpio_platform_data with the I2C adapter number of the master
 bus, the number of bus segments to create and the GPIO pins used
-to control it. See include/linux/i2c-mux-gpio.h for details.
+to control it. See include/linux/platform_data/i2c-mux-gpio.h for details.
 
 E.G. something like this for a MUX providing 4 bus segments
 controlled through 3 GPIO pins:
 
-#include <linux/i2c-mux-gpio.h>
+#include <linux/platform_data/i2c-mux-gpio.h>
 #include <linux/platform_device.h>
 
 static const unsigned myboard_gpiomux_gpios[] = {
index c13b9fb..cb468a5 100644 (file)
@@ -5953,14 +5953,14 @@ GENERIC GPIO I2C DRIVER
 M:     Haavard Skinnemoen <hskinnemoen@gmail.com>
 S:     Supported
 F:     drivers/i2c/busses/i2c-gpio.c
-F:     include/linux/i2c-gpio.h
+F:     include/linux/platform_data/i2c-gpio.h
 
 GENERIC GPIO I2C MULTIPLEXER DRIVER
 M:     Peter Korsgaard <peter.korsgaard@barco.com>
 L:     linux-i2c@vger.kernel.org
 S:     Supported
 F:     drivers/i2c/muxes/i2c-mux-gpio.c
-F:     include/linux/i2c-mux-gpio.h
+F:     include/linux/platform_data/i2c-mux-gpio.h
 F:     Documentation/i2c/muxes/i2c-mux-gpio
 
 GENERIC HDLC (WAN) DRIVERS
@@ -10392,7 +10392,7 @@ F:      arch/arm/mach-omap1/
 F:     arch/arm/plat-omap/
 F:     arch/arm/configs/omap1_defconfig
 F:     drivers/i2c/busses/i2c-omap.c
-F:     include/linux/i2c-omap.h
+F:     include/linux/platform_data/i2c-omap.h
 
 OMAP2+ SUPPORT
 M:     Tony Lindgren <tony@atomide.com>
@@ -10424,7 +10424,7 @@ F:      drivers/regulator/tps65218-regulator.c
 F:     drivers/regulator/tps65910-regulator.c
 F:     drivers/regulator/twl-regulator.c
 F:     drivers/regulator/twl6030-regulator.c
-F:     include/linux/i2c-omap.h
+F:     include/linux/platform_data/i2c-omap.h
 
 ONION OMEGA2+ BOARD
 M:     Harvey Hunt <harveyhuntnexus@gmail.com>
index 937eb1d..ef835d8 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/gpio/machine.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
 #include <linux/platform_data/pca953x.h>
 
 #include <linux/mtd/mtd.h>
index 67d4669..da8f3fc 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
 #include <linux/htcpld.h>
 #include <linux/leds.h>
 #include <linux/spi/spi.h>
index d83ff25..c6537d2 100644 (file)
@@ -27,7 +27,7 @@
 #define __ARCH_ARM_MACH_OMAP1_COMMON_H
 
 #include <linux/mtd/mtd.h>
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
 #include <linux/reboot.h>
 
 #include <asm/exception.h>
index 5bdf3c4..9250f26 100644 (file)
@@ -20,7 +20,7 @@
  */
 
 #include <linux/i2c.h>
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
 #include <mach/mux.h>
 #include "soc.h"
 
index dff3750..129455e 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/mfd/twl.h>
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
 #include <linux/reboot.h>
 #include <linux/irqchip/irq-omap-intc.h>
 
index fe66cf2..d684fac 100644 (file)
@@ -13,7 +13,7 @@
  * XXX these should be marked initdata for multi-OMAP kernels
  */
 
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
 #include <linux/omap-dma.h>
 
 #include "omap_hwmod.h"
index 74eefd3..abef9f6 100644 (file)
@@ -13,7 +13,7 @@
  * XXX these should be marked initdata for multi-OMAP kernels
  */
 
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
 #include <linux/platform_data/hsmmc-omap.h>
 #include <linux/omap-dma.h>
 
index 53e1ac3..c9483bc 100644 (file)
@@ -14,7 +14,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
 
 #include "omap_hwmod.h"
 #include "omap_hwmod_common_data.h"
index d93f9ea..23e6a41 100644 (file)
@@ -15,7 +15,7 @@
  * XXX these should be marked initdata for multi-OMAP kernels
  */
 
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
 #include <linux/power/smartreflex.h>
 #include <linux/platform_data/hsmmc-omap.h>
 
index 234ee0e..a95dbac 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/io.h>
 #include <linux/platform_data/hsmmc-omap.h>
 #include <linux/power/smartreflex.h>
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
 
 #include <linux/omap-dma.h>
 
index 887a30f..115473d 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/io.h>
 #include <linux/platform_data/hsmmc-omap.h>
 #include <linux/power/smartreflex.h>
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
 
 #include <linux/omap-dma.h>
 
index a27c2fe..e6c7061 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/io.h>
 #include <linux/platform_data/hsmmc-omap.h>
 #include <linux/power/smartreflex.h>
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
 
 #include <linux/omap-dma.h>
 
index 0adb1bd..4d475f6 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/wm97xx.h>
 #include <linux/power_supply.h>
 #include <linux/usb/gpio_vbus.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
 #include <linux/gpio/machine.h>
 
 #include <asm/mach-types.h>
index 207dcc2..ab2f892 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/sched.h>
 #include <linux/gpio.h>
 #include <linux/jiffies.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
 #include <linux/gpio/machine.h>
 #include <linux/platform_data/i2c-pxa.h>
 #include <linux/serial_8250.h>
index f45aed2..406487e 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
 #include <linux/leds.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
 
 #include "generic.h"
 
index 4e79dbd..fa75d75 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/leds.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
 #include <linux/gpio/machine.h>
 #include <asm/bootinfo.h>
 #include <asm/idle.h>
index d7d232d..3cba60f 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
-#include <linux/i2c-pca-platform.h>
+#include <linux/platform_data/i2c-pca-platform.h>
 #include <linux/i2c-algo-pca.h>
 #include <linux/usb/r8a66597.h>
 #include <linux/sh_intc.h>
index 3df0efd..4a34f31 100644 (file)
@@ -519,9 +519,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
                        }
                }
        } else {                /* normal 7bit address  */
-               addr = msg->addr << 1;
-               if (flags & I2C_M_RD)
-                       addr |= 1;
+               addr = i2c_8bit_addr_from_msg(msg);
                if (flags & I2C_M_REV_DIR_ADDR)
                        addr ^= 1;
                ret = try_address(i2c_adap, addr, retries);
index e370804..883a290 100644 (file)
@@ -112,11 +112,8 @@ static int pca_address(struct i2c_algo_pca_data *adap,
                       struct i2c_msg *msg)
 {
        int sta = pca_get_con(adap);
-       int addr;
+       int addr = i2c_8bit_addr_from_msg(msg);
 
-       addr = ((0x7f & msg->addr) << 1);
-       if (msg->flags & I2C_M_RD)
-               addr |= 1;
        DEB2("=== SLAVE ADDRESS %#04x+%c=%#04x\n",
             msg->addr, msg->flags & I2C_M_RD ? 'R' : 'W', addr);
 
index 270d84b..5c29a4d 100644 (file)
@@ -291,13 +291,9 @@ static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf,
 static int pcf_doAddress(struct i2c_algo_pcf_data *adap,
                         struct i2c_msg *msg)
 {
-       unsigned short flags = msg->flags;
-       unsigned char addr;
+       unsigned char addr = i2c_8bit_addr_from_msg(msg);
 
-       addr = msg->addr << 1;
-       if (flags & I2C_M_RD)
-               addr |= 1;
-       if (flags & I2C_M_REV_DIR_ADDR)
+       if (msg->flags & I2C_M_REV_DIR_ADDR)
                addr ^= 1;
        i2c_outb(adap, addr);
 
index fce9f2c..4f8df2e 100644 (file)
@@ -943,6 +943,7 @@ config I2C_STM32F4
 config I2C_STM32F7
        tristate "STMicroelectronics STM32F7 I2C support"
        depends on ARCH_STM32 || COMPILE_TEST
+       select I2C_SLAVE
        help
          Enable this option to add support for STM32 I2C controller embedded
          in STM32F7 SoCs.
index 189e34b..5a86914 100644 (file)
@@ -94,7 +94,8 @@ 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
-obj-$(CONFIG_I2C_STM32F7)      += i2c-stm32f7.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
index 7d4aeb4..60e4d0e 100644 (file)
@@ -335,13 +335,12 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
 {
        u32 command = ASPEED_I2CD_M_START_CMD | ASPEED_I2CD_M_TX_CMD;
        struct i2c_msg *msg = &bus->msgs[bus->msgs_index];
-       u8 slave_addr = msg->addr << 1;
+       u8 slave_addr = i2c_8bit_addr_from_msg(msg);
 
        bus->master_state = ASPEED_I2C_MASTER_START;
        bus->buf_index = 0;
 
        if (msg->flags & I2C_M_RD) {
-               slave_addr |= 1;
                command |= ASPEED_I2CD_M_RX_CMD;
                /* Need to let the hardware know to NACK after RX. */
                if (msg->len == 1 && !(msg->flags & I2C_M_RECV_LEN))
index bfd1fdf..3f3e8b3 100644 (file)
@@ -518,8 +518,16 @@ static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id)
         * the RXRDY interrupt first in order to not keep garbage data in the
         * Receive Holding Register for the next transfer.
         */
-       if (irqstatus & AT91_TWI_RXRDY)
-               at91_twi_read_next_byte(dev);
+       if (irqstatus & AT91_TWI_RXRDY) {
+               /*
+                * Read all available bytes at once by polling RXRDY usable w/
+                * and w/o FIFO. With FIFO enabled we could also read RXFL and
+                * avoid polling RXRDY.
+                */
+               do {
+                       at91_twi_read_next_byte(dev);
+               } while (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY);
+       }
 
        /*
         * When a NACK condition is detected, the I2C controller sets the NACK,
index 13f0748..8e60048 100644 (file)
@@ -351,13 +351,15 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
                 *   addr_2: addr[7:0]
                 */
                addr_1 = 0xF0 | ((msg->addr >> 7) & 0x06);
+               if (i2c_m_rd(msg))
+                       addr_1 |= 1;    /* Set the R/nW bit of the address */
                addr_2 = msg->addr & 0xFF;
        } else {
                /* 7-bit address
                 *   addr_1: addr[6:0] | (R/nW)
                 *   addr_2: dont care
                 */
-               addr_1 = (msg->addr << 1) & 0xFF;
+               addr_1 = i2c_8bit_addr_from_msg(msg);
                addr_2 = 0;
        }
 
@@ -365,7 +367,6 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
                /* I2C read transfer */
                rx_xfer = i2c_m_recv_len(msg) ? I2C_SMBUS_BLOCK_MAX : msg->len;
                tx_xfer = 0;
-               addr_1 |= 1;    /* Set the R/nW bit of the address */
        } else {
                /* I2C write transfer */
                rx_xfer = 0;
@@ -532,23 +533,23 @@ static int axxia_i2c_probe(struct platform_device *pdev)
        if (idev->bus_clk_rate == 0)
                idev->bus_clk_rate = 100000;    /* default clock rate */
 
+       ret = clk_prepare_enable(idev->i2c_clk);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to enable clock\n");
+               return ret;
+       }
+
        ret = axxia_i2c_init(idev);
        if (ret) {
                dev_err(&pdev->dev, "failed to initialize\n");
-               return ret;
+               goto error_disable_clk;
        }
 
        ret = devm_request_irq(&pdev->dev, irq, axxia_i2c_isr, 0,
                               pdev->name, idev);
        if (ret) {
                dev_err(&pdev->dev, "failed to claim IRQ%d\n", irq);
-               return ret;
-       }
-
-       ret = clk_prepare_enable(idev->i2c_clk);
-       if (ret) {
-               dev_err(&pdev->dev, "failed to enable clock\n");
-               return ret;
+               goto error_disable_clk;
        }
 
        i2c_set_adapdata(&idev->adapter, idev);
@@ -563,12 +564,14 @@ static int axxia_i2c_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, idev);
 
        ret = i2c_add_adapter(&idev->adapter);
-       if (ret) {
-               clk_disable_unprepare(idev->i2c_clk);
-               return ret;
-       }
+       if (ret)
+               goto error_disable_clk;
 
        return 0;
+
+error_disable_clk:
+       clk_disable_unprepare(idev->i2c_clk);
+       return ret;
 }
 
 static int axxia_i2c_remove(struct platform_device *pdev)
index 27ebd90..48914df 100644 (file)
@@ -149,18 +149,17 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
        return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 + offset;
 }
 
-void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable)
-{
-       dw_writel(dev, enable, DW_IC_ENABLE);
-}
-
-void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable)
+void __i2c_dw_disable(struct dw_i2c_dev *dev)
 {
        int timeout = 100;
 
        do {
-               __i2c_dw_enable(dev, enable);
-               if ((dw_readl(dev, DW_IC_ENABLE_STATUS) & 1) == enable)
+               __i2c_dw_disable_nowait(dev);
+               /*
+                * The enable status register may be unimplemented, but
+                * in that case this test reads zero and exits the loop.
+                */
+               if ((dw_readl(dev, DW_IC_ENABLE_STATUS) & 1) == 0)
                        return;
 
                /*
@@ -171,8 +170,7 @@ void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable)
                usleep_range(25, 250);
        } while (timeout--);
 
-       dev_warn(dev->dev, "timeout in %sabling adapter\n",
-                enable ? "en" : "dis");
+       dev_warn(dev->dev, "timeout in disabling adapter\n");
 }
 
 unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev)
@@ -277,7 +275,7 @@ u32 i2c_dw_func(struct i2c_adapter *adap)
 void i2c_dw_disable(struct dw_i2c_dev *dev)
 {
        /* Disable controller */
-       __i2c_dw_enable_and_wait(dev, false);
+       __i2c_dw_disable(dev);
 
        /* Disable all interupts */
        dw_writel(dev, 0, DW_IC_INTR_MASK);
index 8707c76..d690e64 100644 (file)
@@ -297,8 +297,6 @@ u32 dw_readl(struct dw_i2c_dev *dev, int offset);
 void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
 u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset);
 u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset);
-void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable);
-void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable);
 unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev);
 int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare);
 int i2c_dw_acquire_lock(struct dw_i2c_dev *dev);
@@ -309,6 +307,18 @@ u32 i2c_dw_func(struct i2c_adapter *adap);
 void i2c_dw_disable(struct dw_i2c_dev *dev);
 void i2c_dw_disable_int(struct dw_i2c_dev *dev);
 
+static inline void __i2c_dw_enable(struct dw_i2c_dev *dev)
+{
+       dw_writel(dev, 1, DW_IC_ENABLE);
+}
+
+static inline void __i2c_dw_disable_nowait(struct dw_i2c_dev *dev)
+{
+       dw_writel(dev, 0, DW_IC_ENABLE);
+}
+
+void __i2c_dw_disable(struct dw_i2c_dev *dev);
+
 extern u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev);
 extern int i2c_dw_probe(struct dw_i2c_dev *dev);
 #if IS_ENABLED(CONFIG_I2C_DESIGNWARE_SLAVE)
index 0cdba29..27436a9 100644 (file)
@@ -81,7 +81,7 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev)
        comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1);
 
        /* Disable the adapter */
-       __i2c_dw_enable_and_wait(dev, false);
+       __i2c_dw_disable(dev);
 
        /* Set standard and fast speed deviders for high/low periods */
 
@@ -180,7 +180,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
        u32 ic_con, ic_tar = 0;
 
        /* Disable the adapter */
-       __i2c_dw_enable_and_wait(dev, false);
+       __i2c_dw_disable(dev);
 
        /* If the slave address is ten bit address, enable 10BITADDR */
        ic_con = dw_readl(dev, DW_IC_CON);
@@ -209,7 +209,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
        i2c_dw_disable_int(dev);
 
        /* Enable the adapter */
-       __i2c_dw_enable(dev, true);
+       __i2c_dw_enable(dev);
 
        /* Dummy read to avoid the register getting stuck on Bay Trail */
        dw_readl(dev, DW_IC_ENABLE_STATUS);
@@ -462,7 +462,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
         * additional interrupts are a hardware bug or this driver doesn't
         * handle them correctly yet.
         */
-       __i2c_dw_enable(dev, false);
+       __i2c_dw_disable_nowait(dev);
 
        if (dev->msg_err) {
                ret = dev->msg_err;
index d42558d..8ce2cd3 100644 (file)
@@ -75,7 +75,7 @@ static int i2c_dw_init_slave(struct dw_i2c_dev *dev)
        comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1);
 
        /* Disable the adapter. */
-       __i2c_dw_enable_and_wait(dev, false);
+       __i2c_dw_disable(dev);
 
        /* Configure SDA Hold Time if required. */
        reg = dw_readl(dev, DW_IC_COMP_VERSION);
@@ -119,11 +119,11 @@ static int i2c_dw_reg_slave(struct i2c_client *slave)
         * Set slave address in the IC_SAR register,
         * the address to which the DW_apb_i2c responds.
         */
-       __i2c_dw_enable(dev, false);
+       __i2c_dw_disable_nowait(dev);
        dw_writel(dev, slave->addr, DW_IC_SAR);
        dev->slave = slave;
 
-       __i2c_dw_enable(dev, true);
+       __i2c_dw_enable(dev);
 
        dev->cmd_err = 0;
        dev->msg_write_idx = 0;
index f718ee4..3f28317 100644 (file)
@@ -360,11 +360,11 @@ static int diolan_usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
                        if (ret < 0)
                                goto abort;
                }
+               ret = diolan_i2c_put_byte_ack(dev,
+                                             i2c_8bit_addr_from_msg(pmsg));
+               if (ret < 0)
+                       goto abort;
                if (pmsg->flags & I2C_M_RD) {
-                       ret =
-                           diolan_i2c_put_byte_ack(dev, (pmsg->addr << 1) | 1);
-                       if (ret < 0)
-                               goto abort;
                        for (j = 0; j < pmsg->len; j++) {
                                u8 byte;
                                bool ack = j < pmsg->len - 1;
@@ -393,9 +393,6 @@ static int diolan_usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
                                pmsg->buf[j] = byte;
                        }
                } else {
-                       ret = diolan_i2c_put_byte_ack(dev, pmsg->addr << 1);
-                       if (ret < 0)
-                               goto abort;
                        for (j = 0; j < pmsg->len; j++) {
                                ret = diolan_i2c_put_byte_ack(dev,
                                                              pmsg->buf[j]);
index aa336ba..5f2bab8 100644 (file)
@@ -144,8 +144,7 @@ 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, cur_msg->addr << 1 |
-                       (cur_msg->flags & I2C_M_RD ? 1 : 0));
+       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)
index bdeab01..835d54a 100644 (file)
@@ -414,7 +414,7 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
                iowrite32(addr_8_lsb, p + PCH_I2CDR);
        } else {
                /* set 7 bit slave address and R/W bit as 0 */
-               iowrite32(addr << 1, p + PCH_I2CDR);
+               iowrite32(i2c_8bit_addr_from_msg(msgs), p + PCH_I2CDR);
                if (first)
                        pch_i2c_start(adap);
        }
@@ -538,8 +538,7 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
                iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
        } else {
                /* 7 address bits + R/W bit */
-               addr = (((addr) << 1) | (I2C_RD));
-               iowrite32(addr, p + PCH_I2CDR);
+               iowrite32(i2c_8bit_addr_from_msg(msgs), p + PCH_I2CDR);
        }
 
        /* check if it is the first message */
index d2e8448..ba9b6ea 100644 (file)
@@ -149,7 +149,7 @@ static int __em_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
        em_clear_set_bit(priv, 0, I2C_BIT_STT0, I2C_OFS_IICC0);
 
        /* Send slave address and R/W type */
-       writeb((msg->addr << 1) | read, priv->base + I2C_OFS_IIC0);
+       writeb(i2c_8bit_addr_from_msg(msg), priv->base + I2C_OFS_IIC0);
 
        /* Wait for transaction */
        status = em_i2c_wait_for_event(priv);
index 12ec848..de82ad8 100644 (file)
@@ -707,7 +707,7 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap,
                        struct i2c_msg *msgs, int num)
 {
        struct exynos5_i2c *i2c = adap->algo_data;
-       int i = 0, ret = 0, stop = 0;
+       int i, ret;
 
        if (i2c->suspended) {
                dev_err(i2c->dev, "HS-I2C is not initialized.\n");
@@ -718,30 +718,15 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap,
        if (ret)
                return ret;
 
-       for (i = 0; i < num; i++, msgs++) {
-               stop = (i == num - 1);
-
-               ret = exynos5_i2c_xfer_msg(i2c, msgs, stop);
-
-               if (ret < 0)
-                       goto out;
-       }
-
-       if (i == num) {
-               ret = num;
-       } else {
-               /* Only one message, cannot access the device */
-               if (i == 1)
-                       ret = -EREMOTEIO;
-               else
-                       ret = i;
-
-               dev_warn(i2c->dev, "xfer message failed\n");
+       for (i = 0; i < num; ++i) {
+               ret = exynos5_i2c_xfer_msg(i2c, msgs + i, i + 1 == num);
+               if (ret)
+                       break;
        }
 
- out:
        clk_disable(i2c->clk);
-       return ret;
+
+       return ret ?: num;
 }
 
 static u32 exynos5_i2c_func(struct i2c_adapter *adap)
index 58abb3e..005e6e0 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index bb68957..061a4bf 100644 (file)
@@ -73,7 +73,6 @@
 #define I2C_OVER_INTR          BIT(0)
 
 #define HIX5I2C_MAX_FREQ       400000          /* 400k */
-#define HIX5I2C_READ_OPERATION 0x01
 
 enum hix5hd2_i2c_state {
        HIX5I2C_STAT_RW_ERR = -1,
@@ -311,12 +310,8 @@ static void hix5hd2_i2c_message_start(struct hix5hd2_i2c_priv *priv, int stop)
        hix5hd2_i2c_clr_all_irq(priv);
        hix5hd2_i2c_enable_irq(priv);
 
-       if (priv->msg->flags & I2C_M_RD)
-               writel_relaxed((priv->msg->addr << 1) | HIX5I2C_READ_OPERATION,
-                              priv->regs + HIX5I2C_TXR);
-       else
-               writel_relaxed(priv->msg->addr << 1,
-                              priv->regs + HIX5I2C_TXR);
+       writel_relaxed(i2c_8bit_addr_from_msg(priv->msg),
+                      priv->regs + HIX5I2C_TXR);
 
        writel_relaxed(I2C_WRITE | I2C_START, priv->regs + HIX5I2C_COM);
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -377,17 +372,7 @@ static int hix5hd2_i2c_xfer(struct i2c_adapter *adap,
                        goto out;
        }
 
-       if (i == num) {
-               ret = num;
-       } else {
-               /* Only one message, cannot access the device */
-               if (i == 1)
-                       ret = -EREMOTEIO;
-               else
-                       ret = i;
-
-               dev_warn(priv->dev, "xfer message failed\n");
-       }
+       ret = num;
 
 out:
        pm_runtime_mark_last_busy(priv->dev);
@@ -471,7 +456,6 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev)
                goto err_clk;
        }
 
-       pm_suspend_ignore_children(&pdev->dev, true);
        pm_runtime_set_autosuspend_delay(priv->dev, MSEC_PER_SEC);
        pm_runtime_use_autosuspend(priv->dev);
        pm_runtime_set_active(priv->dev);
index e0d59e9..aa72660 100644 (file)
 
 #if IS_ENABLED(CONFIG_I2C_MUX_GPIO) && defined CONFIG_DMI
 #include <linux/gpio.h>
-#include <linux/i2c-mux-gpio.h>
+#include <linux/platform_data/i2c-mux-gpio.h>
 #endif
 
 /* I801 SMBus address offsets */
@@ -1710,7 +1710,7 @@ static void i801_shutdown(struct pci_dev *dev)
        pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int i801_suspend(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
@@ -1731,8 +1731,7 @@ static int i801_resume(struct device *dev)
 }
 #endif
 
-static UNIVERSAL_DEV_PM_OPS(i801_pm_ops, i801_suspend,
-                           i801_resume, NULL);
+static SIMPLE_DEV_PM_OPS(i801_pm_ops, i801_suspend, i801_resume);
 
 static struct pci_driver i801_driver = {
        .name           = "i801_smbus",
index 961c5f4..6f6e1df 100644 (file)
@@ -561,9 +561,6 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 
        DBG2("%d: iic_xfer, %d msg(s)\n", dev->idx, num);
 
-       if (!num)
-               return 0;
-
        /* Check the sanity of the passed messages.
         * Uhh, generic i2c layer is more suitable place for such code...
         */
index e6da2c7..6d975f5 100644 (file)
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * This is i.MX low power i2c controller driver.
  *
  * Copyright 2016 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  */
 
 #include <linux/clk.h>
@@ -180,15 +170,13 @@ static int lpi2c_imx_start(struct lpi2c_imx_struct *lpi2c_imx,
                           struct i2c_msg *msgs)
 {
        unsigned int temp;
-       u8 read;
 
        temp = readl(lpi2c_imx->base + LPI2C_MCR);
        temp |= MCR_RRF | MCR_RTF;
        writel(temp, lpi2c_imx->base + LPI2C_MCR);
        writel(0x7f00, lpi2c_imx->base + LPI2C_MSR);
 
-       read = msgs->flags & I2C_M_RD;
-       temp = (msgs->addr << 1 | read) | (GEN_START << 8);
+       temp = i2c_8bit_addr_from_msg(msgs) | (GEN_START << 8);
        writel(temp, lpi2c_imx->base + LPI2C_MTDR);
 
        return lpi2c_imx_bus_busy(lpi2c_imx);
index d7267dd..0207e19 100644 (file)
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  *     Copyright (C) 2002 Motorola GSG-China
  *
- *     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.
- *
  * Author:
  *     Darius Augulis, Teltonika Inc.
  *
@@ -630,7 +621,7 @@ static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
         * Write slave address.
         * The first byte must be transmitted by the CPU.
         */
-       imx_i2c_write_reg(msgs->addr << 1, i2c_imx, IMX_I2C_I2DR);
+       imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
        reinit_completion(&i2c_imx->dma->cmd_complete);
        time_left = wait_for_completion_timeout(
                                &i2c_imx->dma->cmd_complete,
@@ -760,10 +751,10 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
        int i, result;
 
        dev_dbg(&i2c_imx->adapter.dev, "<%s> write slave address: addr=0x%x\n",
-               __func__, msgs->addr << 1);
+               __func__, i2c_8bit_addr_from_msg(msgs));
 
        /* write slave address */
-       imx_i2c_write_reg(msgs->addr << 1, i2c_imx, IMX_I2C_I2DR);
+       imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
        result = i2c_imx_trx_complete(i2c_imx);
        if (result)
                return result;
@@ -796,10 +787,10 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
 
        dev_dbg(&i2c_imx->adapter.dev,
                "<%s> write slave address: addr=0x%x\n",
-               __func__, (msgs->addr << 1) | 0x01);
+               __func__, i2c_8bit_addr_from_msg(msgs));
 
        /* write slave address */
-       imx_i2c_write_reg((msgs->addr << 1) | 0x01, i2c_imx, IMX_I2C_I2DR);
+       imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
        result = i2c_imx_trx_complete(i2c_imx);
        if (result)
                return result;
index e879190..1c874aa 100644 (file)
@@ -124,15 +124,14 @@ static int kempld_i2c_process(struct kempld_i2c_data *i2c)
                /* 10 bit address? */
                if (i2c->msg->flags & I2C_M_TEN) {
                        addr = 0xf0 | ((i2c->msg->addr >> 7) & 0x6);
+                       /* Set read bit if necessary */
+                       addr |= (i2c->msg->flags & I2C_M_RD) ? 1 : 0;
                        i2c->state = STATE_ADDR10;
                } else {
-                       addr = (i2c->msg->addr << 1);
+                       addr = i2c_8bit_addr_from_msg(i2c->msg);
                        i2c->state = STATE_START;
                }
 
-               /* Set read bit if necessary */
-               addr |= (i2c->msg->flags & I2C_M_RD) ? 1 : 0;
-
                kempld_write8(pld, KEMPLD_I2C_DATA, addr);
                kempld_write8(pld, KEMPLD_I2C_CMD, I2C_CMD_START);
 
index 4c28fa2..745ed43 100644 (file)
 #define MLXCPLD_I2C_VALID_FLAG         (I2C_M_RECV_LEN | I2C_M_RD)
 #define MLXCPLD_I2C_BUS_NUM            1
 #define MLXCPLD_I2C_DATA_REG_SZ                36
+#define MLXCPLD_I2C_DATA_SZ_BIT                BIT(5)
+#define MLXCPLD_I2C_DATA_SZ_MASK       GENMASK(6, 5)
+#define MLXCPLD_I2C_SMBUS_BLK_BIT      BIT(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 */
 
 /* LPC I2C registers */
-#define MLXCPLD_LPCI2C_LPF_REG         0x0
+#define MLXCPLD_LPCI2C_CPBLTY_REG      0x0
 #define MLXCPLD_LPCI2C_CTRL_REG                0x1
 #define MLXCPLD_LPCI2C_HALF_CYC_REG    0x4
 #define MLXCPLD_LPCI2C_I2C_HOLD_REG    0x5
@@ -83,6 +86,7 @@ struct mlxcpld_i2c_priv {
        struct mutex lock;
        struct  mlxcpld_i2c_curr_xfer xfer;
        struct device *dev;
+       bool smbus_block;
 };
 
 static void mlxcpld_i2c_lpc_write_buf(u8 *data, u8 len, u32 addr)
@@ -230,7 +234,7 @@ static void mlxcpld_i2c_set_transf_data(struct mlxcpld_i2c_priv *priv,
         * All upper layers currently are never use transfer with more than
         * 2 messages. Actually, it's also not so relevant in Mellanox systems
         * because of HW limitation. Max size of transfer is not more than 32
-        * bytes in the current x86 LPCI2C bridge.
+        * or 68 bytes in the current x86 LPCI2C bridge.
         */
        priv->xfer.cmd = msgs[num - 1].flags & I2C_M_RD;
 
@@ -295,7 +299,7 @@ static int mlxcpld_i2c_wait_for_free(struct mlxcpld_i2c_priv *priv)
 static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv)
 {
        int status, i, timeout = 0;
-       u8 datalen;
+       u8 datalen, val;
 
        do {
                usleep_range(MLXCPLD_I2C_POLL_TIME / 2, MLXCPLD_I2C_POLL_TIME);
@@ -324,9 +328,22 @@ static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv)
                 * Actual read data len will be always the same as
                 * requested len. 0xff (line pull-up) will be returned
                 * if slave has no data to return. Thus don't read
-                * MLXCPLD_LPCI2C_NUM_DAT_REG reg from CPLD.
+                * MLXCPLD_LPCI2C_NUM_DAT_REG reg from CPLD.  Only in case of
+                * SMBus block read transaction data len can be different,
+                * check this case.
                 */
-               datalen = priv->xfer.data_len;
+               mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG, &val,
+                                     1);
+               if (priv->smbus_block && (val & MLXCPLD_I2C_SMBUS_BLK_BIT)) {
+                       mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_NUM_DAT_REG,
+                                             &datalen, 1);
+                       if (unlikely(datalen > (I2C_SMBUS_BLOCK_MAX + 1))) {
+                               dev_err(priv->dev, "Incorrect smbus block read message len\n");
+                               return -E2BIG;
+                       }
+               } else {
+                       datalen = priv->xfer.data_len;
+               }
 
                mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_DATA_REG,
                                      priv->xfer.msg[i].buf, datalen);
@@ -344,12 +361,20 @@ static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv)
 static void mlxcpld_i2c_xfer_msg(struct mlxcpld_i2c_priv *priv)
 {
        int i, len = 0;
-       u8 cmd;
+       u8 cmd, val;
 
        mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_DAT_REG,
                               &priv->xfer.data_len, 1);
-       mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG,
-                              &priv->xfer.addr_width, 1);
+
+       val = priv->xfer.addr_width;
+       /* Notify HW about SMBus block read transaction */
+       if (priv->smbus_block && priv->xfer.msg_num >= 2 &&
+           priv->xfer.msg[1].len == 1 &&
+           (priv->xfer.msg[1].flags & I2C_M_RECV_LEN) &&
+           (priv->xfer.msg[1].flags & I2C_M_RD))
+               val |= MLXCPLD_I2C_SMBUS_BLK_BIT;
+
+       mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG, &val, 1);
 
        for (i = 0; i < priv->xfer.msg_num; i++) {
                if ((priv->xfer.msg[i].flags & I2C_M_RD) != I2C_M_RD) {
@@ -425,7 +450,14 @@ static int mlxcpld_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
 
 static u32 mlxcpld_i2c_func(struct i2c_adapter *adap)
 {
-       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA;
+       struct mlxcpld_i2c_priv *priv = i2c_get_adapdata(adap);
+
+       if (priv->smbus_block)
+               return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+                       I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_BLOCK_DATA;
+       else
+               return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+                       I2C_FUNC_SMBUS_I2C_BLOCK;
 }
 
 static const struct i2c_algorithm mlxcpld_i2c_algo = {
@@ -440,6 +472,13 @@ static const struct i2c_adapter_quirks mlxcpld_i2c_quirks = {
        .max_comb_1st_msg_len = 4,
 };
 
+static const struct i2c_adapter_quirks mlxcpld_i2c_quirks_ext = {
+       .flags = I2C_AQ_COMB_WRITE_THEN_READ,
+       .max_read_len = MLXCPLD_I2C_DATA_REG_SZ * 2 - MLXCPLD_I2C_MAX_ADDR_LEN,
+       .max_write_len = MLXCPLD_I2C_DATA_REG_SZ * 2,
+       .max_comb_1st_msg_len = 4,
+};
+
 static struct i2c_adapter mlxcpld_i2c_adapter = {
        .owner          = THIS_MODULE,
        .name           = "i2c-mlxcpld",
@@ -454,6 +493,7 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev)
 {
        struct mlxcpld_i2c_priv *priv;
        int err;
+       u8 val;
 
        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
@@ -466,6 +506,16 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev)
 
        /* Register with i2c layer */
        mlxcpld_i2c_adapter.timeout = usecs_to_jiffies(MLXCPLD_I2C_XFER_TO);
+       /* Read capability register */
+       mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_CPBLTY_REG, &val, 1);
+       /* Check support for extended transaction length */
+       if ((val & MLXCPLD_I2C_DATA_SZ_MASK) == MLXCPLD_I2C_DATA_SZ_BIT)
+               mlxcpld_i2c_adapter.quirks = &mlxcpld_i2c_quirks_ext;
+       /* Check support for smbus block transaction */
+       if (val & MLXCPLD_I2C_SMBUS_BLK_BIT)
+               priv->smbus_block = true;
+       if (pdev->id >= -1)
+               mlxcpld_i2c_adapter.nr = pdev->id;
        priv->adap = mlxcpld_i2c_adapter;
        priv->adap.dev.parent = &pdev->dev;
        priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR;
index cf23a74..1e57f58 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/of_irq.h>
 #include <linux/platform_device.h>
 #include <linux/scatterlist.h>
@@ -734,7 +735,6 @@ static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c)
 
 static int mtk_i2c_probe(struct platform_device *pdev)
 {
-       const struct of_device_id *of_id;
        int ret = 0;
        struct mtk_i2c *i2c;
        struct clk *clk;
@@ -761,11 +761,7 @@ static int mtk_i2c_probe(struct platform_device *pdev)
 
        init_completion(&i2c->msg_complete);
 
-       of_id = of_match_node(mtk_i2c_of_match, pdev->dev.of_node);
-       if (!of_id)
-               return -EINVAL;
-
-       i2c->dev_comp = of_id->data;
+       i2c->dev_comp = of_device_get_match_data(&pdev->dev);
        i2c->adap.dev.of_node = pdev->dev.of_node;
        i2c->dev = &pdev->dev;
        i2c->adap.dev.parent = &pdev->dev;
index e617bd6..642c589 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Freescale MXS I2C bus driver
  *
@@ -7,12 +8,6 @@
  * based on a (non-working) driver which was:
  *
  * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * 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.
- *
  */
 
 #include <linux/slab.h>
@@ -180,9 +175,10 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
        struct dma_async_tx_descriptor *desc;
        struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
 
+       i2c->addr_data = i2c_8bit_addr_from_msg(msg);
+
        if (msg->flags & I2C_M_RD) {
                i2c->dma_read = true;
-               i2c->addr_data = (msg->addr << 1) | I2C_SMBUS_READ;
 
                /*
                 * SELECT command.
@@ -240,7 +236,6 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
                }
        } else {
                i2c->dma_read = false;
-               i2c->addr_data = (msg->addr << 1) | I2C_SMBUS_WRITE;
 
                /*
                 * WRITE command.
@@ -371,7 +366,7 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
                        struct i2c_msg *msg, uint32_t flags)
 {
        struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
-       uint32_t addr_data = msg->addr << 1;
+       uint32_t addr_data = i2c_8bit_addr_from_msg(msg);
        uint32_t data = 0;
        int i, ret, xlen = 0, xmit = 0;
        uint32_t start;
@@ -411,8 +406,6 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
                 */
                BUG_ON(msg->len > 4);
 
-               addr_data |= I2C_SMBUS_READ;
-
                /* SELECT command. */
                mxs_i2c_pio_trigger_write_cmd(i2c, MXS_CMD_I2C_SELECT,
                                              addr_data);
@@ -450,7 +443,6 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
                 * fast enough. It is possible to transfer arbitrary amount
                 * of data using PIO write.
                 */
-               addr_data |= I2C_SMBUS_WRITE;
 
                /*
                 * The LSB of data buffer is the first byte blasted across
index 49c7c0c..0ed5a41 100644 (file)
@@ -1012,8 +1012,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
                goto err_no_mem;
        }
 
-       pm_suspend_ignore_children(&adev->dev, true);
-
        dev->clk = devm_clk_get(&adev->dev, NULL);
        if (IS_ERR(dev->clk)) {
                dev_err(&adev->dev, "could not get i2c clock\n");
index 45ae3c0..88444ef 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/wait.h>
-#include <linux/i2c-ocores.h>
+#include <linux/platform_data/i2c-ocores.h>
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/log2.h>
@@ -222,10 +222,7 @@ static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
        i2c->nmsgs = num;
        i2c->state = STATE_START;
 
-       oc_setreg(i2c, OCI2C_DATA,
-                       (i2c->msg->addr << 1) |
-                       ((i2c->msg->flags & I2C_M_RD) ? 1:0));
-
+       oc_setreg(i2c, OCI2C_DATA, i2c_8bit_addr_from_msg(i2c->msg));
        oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START);
 
        if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) ||
index b9172f0..65d06a8 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/slab.h>
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
 #include <linux/pm_runtime.h>
 #include <linux/pinctrl/consumer.h>
 
index 0aabb7e..dc2a23f 100644 (file)
@@ -94,8 +94,6 @@ static int i2c_opal_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
         */
        memset(&req, 0, sizeof(req));
        switch(num) {
-       case 0:
-               return 0;
        case 1:
                req.type = (msgs[0].flags & I2C_M_RD) ?
                        OPAL_I2C_RAW_READ : OPAL_I2C_RAW_WRITE;
@@ -114,8 +112,6 @@ static int i2c_opal_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
                req.size = cpu_to_be32(msgs[1].len);
                req.buffer_ra = cpu_to_be64(__pa(msgs[1].buf));
                break;
-       default:
-               return -EOPNOTSUPP;
        }
 
        rc = i2c_opal_send_request(opal_id, &req);
index df1dbc9..55fd5c6 100644 (file)
@@ -121,7 +121,7 @@ static int pasemi_i2c_xfer_msg(struct i2c_adapter *adapter,
 
        read = msg->flags & I2C_M_RD ? 1 : 0;
 
-       TXFIFO_WR(smbus, MTXFIFO_START | (msg->addr << 1) | read);
+       TXFIFO_WR(smbus, MTXFIFO_START | i2c_8bit_addr_from_msg(msg));
 
        if (read) {
                TXFIFO_WR(smbus, msg->len | MTXFIFO_READ |
index bc2707f..de3fe6e 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-algo-pca.h>
-#include <linux/i2c-pca-platform.h>
+#include <linux/platform_data/i2c-pca-platform.h>
 #include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/io.h>
index a542041..6e0e546 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/timer.h>
 #include <linux/completion.h>
 #include <linux/platform_device.h>
-#include <linux/i2c-pnx.h>
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 #define I2C_PNX_SPEED_KHZ_DEFAULT      100
 #define I2C_PNX_REGION_SIZE            0x100
 
+struct i2c_pnx_mif {
+       int                     ret;            /* Return value */
+       int                     mode;           /* Interface mode */
+       struct completion       complete;       /* I/O completion */
+       struct timer_list       timer;          /* Timeout */
+       u8 *                    buf;            /* Data buffer */
+       int                     len;            /* Length of data buffer */
+       int                     order;          /* RX Bytes to order via TX */
+};
+
+struct i2c_pnx_algo_data {
+       void __iomem            *ioaddr;
+       struct i2c_pnx_mif      mif;
+       int                     last;
+       struct clk              *clk;
+       struct i2c_adapter      adapter;
+       int                     irq;
+       u32                     timeout;
+};
+
 enum {
        mstatus_tdi = 0x00000001,
        mstatus_afi = 0x00000002,
index ebbf9cd..c86c3ae 100644 (file)
  */
 #define TOUT_MIN                       2
 
+/* I2C Frequency Modes */
+#define I2C_STANDARD_FREQ              100000
+#define I2C_FAST_MODE_FREQ             400000
+#define I2C_FAST_MODE_PLUS_FREQ                1000000
+
 /* Default values. Use these if FW query fails */
-#define DEFAULT_CLK_FREQ 100000
+#define DEFAULT_CLK_FREQ I2C_STANDARD_FREQ
 #define DEFAULT_SRC_CLK 20000000
 
 /*
 /* TAG length for DATA READ in RX FIFO  */
 #define READ_RX_TAGS_LEN               2
 
+static unsigned int scl_freq;
+module_param_named(scl_freq, scl_freq, uint, 0444);
+MODULE_PARM_DESC(scl_freq, "SCL frequency override");
+
 /*
  * count: no of blocks
  * pos: current block number
@@ -453,7 +462,7 @@ static void qup_i2c_write_tx_fifo_v1(struct qup_i2c_dev *qup)
 {
        struct qup_i2c_block *blk = &qup->blk;
        struct i2c_msg *msg = qup->msg;
-       u32 addr = msg->addr << 1;
+       u32 addr = i2c_8bit_addr_from_msg(msg);
        u32 qup_tag;
        int idx;
        u32 val;
@@ -1648,6 +1657,12 @@ static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup)
        clk_disable_unprepare(qup->pclk);
 }
 
+static const struct acpi_device_id qup_i2c_acpi_match[] = {
+       { "QCOM8010"},
+       { },
+};
+MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_match);
+
 static int qup_i2c_probe(struct platform_device *pdev)
 {
        static const int blk_sizes[] = {4, 16, 32};
@@ -1669,10 +1684,15 @@ static int qup_i2c_probe(struct platform_device *pdev)
        init_completion(&qup->xfer);
        platform_set_drvdata(pdev, qup);
 
-       ret = device_property_read_u32(qup->dev, "clock-frequency", &clk_freq);
-       if (ret) {
-               dev_notice(qup->dev, "using default clock-frequency %d",
-                       DEFAULT_CLK_FREQ);
+       if (scl_freq) {
+               dev_notice(qup->dev, "Using override frequency of %u\n", scl_freq);
+               clk_freq = scl_freq;
+       } else {
+               ret = device_property_read_u32(qup->dev, "clock-frequency", &clk_freq);
+               if (ret) {
+                       dev_notice(qup->dev, "using default clock-frequency %d",
+                               DEFAULT_CLK_FREQ);
+               }
        }
 
        if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v1.1.1")) {
@@ -1682,7 +1702,10 @@ static int qup_i2c_probe(struct platform_device *pdev)
        } else {
                qup->adap.algo = &qup_i2c_algo_v2;
                is_qup_v1 = false;
-               ret = qup_i2c_req_dma(qup);
+               if (acpi_match_device(qup_i2c_acpi_match, qup->dev))
+                       goto nodma;
+               else
+                       ret = qup_i2c_req_dma(qup);
 
                if (ret == -EPROBE_DEFER)
                        goto fail_dma;
@@ -1734,8 +1757,8 @@ static int qup_i2c_probe(struct platform_device *pdev)
        }
 
 nodma:
-       /* We support frequencies up to FAST Mode (400KHz) */
-       if (!clk_freq || clk_freq > 400000) {
+       /* We support frequencies up to FAST Mode Plus (1MHz) */
+       if (!clk_freq || clk_freq > I2C_FAST_MODE_PLUS_FREQ) {
                dev_err(qup->dev, "clock frequency not supported %d\n",
                        clk_freq);
                return -EINVAL;
@@ -1839,9 +1862,15 @@ nodma:
        size = QUP_INPUT_FIFO_SIZE(io_mode);
        qup->in_fifo_sz = qup->in_blk_sz * (2 << size);
 
-       fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
        hs_div = 3;
-       qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
+       if (clk_freq <= I2C_STANDARD_FREQ) {
+               fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
+               qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
+       } else {
+               /* 33%/66% duty cycle */
+               fs_div = ((src_clk_freq / clk_freq) - 6) * 2 / 3;
+               qup->clk_ctl = ((fs_div / 2) << 16) | (hs_div << 8) | (fs_div & 0xff);
+       }
 
        /*
         * Time it takes for a byte to be clocked out on the bus.
@@ -1959,14 +1988,6 @@ static const struct of_device_id qup_i2c_dt_match[] = {
 };
 MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
 
-#if IS_ENABLED(CONFIG_ACPI)
-static const struct acpi_device_id qup_i2c_acpi_match[] = {
-       { "QCOM8010"},
-       { },
-};
-MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_match);
-#endif
-
 static struct platform_driver qup_i2c_driver = {
        .probe  = qup_i2c_probe,
        .remove = qup_i2c_remove,
index c6915b8..5e310ef 100644 (file)
@@ -329,7 +329,7 @@ static void rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv)
        if (priv->msgs_left == 1)
                priv->flags |= ID_LAST_MSG;
 
-       rcar_i2c_write(priv, ICMAR, (priv->msg->addr << 1) | read);
+       rcar_i2c_write(priv, ICMAR, i2c_8bit_addr_from_msg(priv->msg));
        /*
         * We don't have a test case but the HW engineers say that the write order
         * of ICMSR and ICMCR depends on whether we issue START or REP_START. Since
@@ -542,6 +542,8 @@ static void rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
         * If next received data is the _LAST_, go to STOP phase. Might be
         * overwritten by REP START when setting up a new msg. Not elegant
         * but the only stable sequence for REP START I have found so far.
+        * If you want to change this code, make sure sending one transfer with
+        * four messages (WR-RD-WR-RD) works!
         */
        if (priv->pos + 1 >= msg->len)
                rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
index 95c2f1c..5f1fca7 100644 (file)
@@ -167,15 +167,14 @@ static irqreturn_t riic_tdre_isr(int irq, void *data)
                return IRQ_NONE;
 
        if (riic->bytes_left == RIIC_INIT_MSG) {
-               val = !!(riic->msg->flags & I2C_M_RD);
-               if (val)
+               if (riic->msg->flags & I2C_M_RD)
                        /* On read, switch over to receive interrupt */
                        riic_clear_set_bit(riic, ICIER_TIE, ICIER_RIE, RIIC_ICIER);
                else
                        /* On write, initialize length */
                        riic->bytes_left = riic->msg->len;
 
-               val |= (riic->msg->addr << 1);
+               val = i2c_8bit_addr_from_msg(riic->msg);
        } else {
                val = *riic->buf;
                riic->buf++;
index e1a18d9..b8a2728 100644 (file)
@@ -1326,8 +1326,6 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
        if (ret < 0)
                goto err_clk_notifier;
 
-       dev_info(&pdev->dev, "Initialized RK3xxx I2C bus at %p\n", i2c->regs);
-
        return 0;
 
 err_clk_notifier:
index 9c0f52b..d848cf5 100644 (file)
@@ -62,27 +62,24 @@ static int osif_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
 {
        struct osif_priv *priv = adapter->algo_data;
        struct i2c_msg *pmsg;
-       int ret = 0;
-       int i, cmd;
+       int ret;
+       int i;
 
-       for (i = 0; ret >= 0 && i < num; i++) {
+       for (i = 0; i < num; i++) {
                pmsg = &msgs[i];
 
                if (pmsg->flags & I2C_M_RD) {
-                       cmd = OSIFI2C_READ;
-
-                       ret = osif_usb_read(adapter, cmd, pmsg->flags,
-                                           pmsg->addr, pmsg->buf,
-                                           pmsg->len);
+                       ret = osif_usb_read(adapter, OSIFI2C_READ,
+                                           pmsg->flags, pmsg->addr,
+                                           pmsg->buf, pmsg->len);
                        if (ret != pmsg->len) {
                                dev_err(&adapter->dev, "failure reading data\n");
                                return -EREMOTEIO;
                        }
                } else {
-                       cmd = OSIFI2C_WRITE;
-
-                       ret = osif_usb_write(adapter, cmd, pmsg->flags,
-                                            pmsg->addr, pmsg->buf, pmsg->len);
+                       ret = osif_usb_write(adapter, OSIFI2C_WRITE,
+                                            pmsg->flags, pmsg->addr,
+                                            pmsg->buf, pmsg->len);
                        if (ret != pmsg->len) {
                                dev_err(&adapter->dev, "failure writing data\n");
                                return -EREMOTEIO;
index 5d97510..9fe2b69 100644 (file)
@@ -154,8 +154,6 @@ static const struct of_device_id s3c24xx_i2c_match[] = {
        { .compatible = "samsung,s3c2440-i2c", .data = (void *)QUIRK_S3C2440 },
        { .compatible = "samsung,s3c2440-hdmiphy-i2c",
          .data = (void *)(QUIRK_S3C2440 | QUIRK_HDMIPHY | QUIRK_NO_GPIO) },
-       { .compatible = "samsung,exynos5440-i2c",
-         .data = (void *)(QUIRK_S3C2440 | QUIRK_NO_GPIO) },
        { .compatible = "samsung,exynos5-sata-phy-i2c",
          .data = (void *)(QUIRK_S3C2440 | QUIRK_POLL | QUIRK_NO_GPIO) },
        {},
index d856bc2..5fda418 100644 (file)
@@ -899,17 +899,6 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
        if (resource_size(res) > 0x17)
                pd->flags |= IIC_FLAG_HAS_ICIC67;
 
-       /* Enable Runtime PM for this device.
-        *
-        * Also tell the Runtime PM core to ignore children
-        * for this device since it is valid for us to suspend
-        * this I2C master driver even though the slave devices
-        * on the I2C bus may not be suspended.
-        *
-        * The state of the I2C hardware bus is unaffected by
-        * the Runtime PM state.
-        */
-       pm_suspend_ignore_children(&dev->dev, true);
        pm_runtime_enable(&dev->dev);
        pm_runtime_get_sync(&dev->dev);
 
diff --git a/drivers/i2c/busses/i2c-stm32.c b/drivers/i2c/busses/i2c-stm32.c
new file mode 100644 (file)
index 0000000..d75fbcb
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * i2c-stm32.c
+ *
+ * Copyright (C) M'boumba Cedric Madianga 2017
+ * Author: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
+ *
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#include "i2c-stm32.h"
+
+/* Functions for DMA support */
+struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev,
+                                           dma_addr_t phy_addr,
+                                           u32 txdr_offset,
+                                           u32 rxdr_offset)
+{
+       struct stm32_i2c_dma *dma;
+       struct dma_slave_config dma_sconfig;
+       int ret;
+
+       dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
+       if (!dma)
+               return NULL;
+
+       /* Request and configure I2C TX dma channel */
+       dma->chan_tx = dma_request_slave_channel(dev, "tx");
+       if (!dma->chan_tx) {
+               dev_dbg(dev, "can't request DMA tx channel\n");
+               ret = -EINVAL;
+               goto fail_al;
+       }
+
+       memset(&dma_sconfig, 0, sizeof(dma_sconfig));
+       dma_sconfig.dst_addr = phy_addr + txdr_offset;
+       dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+       dma_sconfig.dst_maxburst = 1;
+       dma_sconfig.direction = DMA_MEM_TO_DEV;
+       ret = dmaengine_slave_config(dma->chan_tx, &dma_sconfig);
+       if (ret < 0) {
+               dev_err(dev, "can't configure tx channel\n");
+               goto fail_tx;
+       }
+
+       /* Request and configure I2C RX dma channel */
+       dma->chan_rx = dma_request_slave_channel(dev, "rx");
+       if (!dma->chan_rx) {
+               dev_err(dev, "can't request DMA rx channel\n");
+               ret = -EINVAL;
+               goto fail_tx;
+       }
+
+       memset(&dma_sconfig, 0, sizeof(dma_sconfig));
+       dma_sconfig.src_addr = phy_addr + rxdr_offset;
+       dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+       dma_sconfig.src_maxburst = 1;
+       dma_sconfig.direction = DMA_DEV_TO_MEM;
+       ret = dmaengine_slave_config(dma->chan_rx, &dma_sconfig);
+       if (ret < 0) {
+               dev_err(dev, "can't configure rx channel\n");
+               goto fail_rx;
+       }
+
+       init_completion(&dma->dma_complete);
+
+       dev_info(dev, "using %s (tx) and %s (rx) for DMA transfers\n",
+                dma_chan_name(dma->chan_tx), dma_chan_name(dma->chan_rx));
+
+       return dma;
+
+fail_rx:
+       dma_release_channel(dma->chan_rx);
+fail_tx:
+       dma_release_channel(dma->chan_tx);
+fail_al:
+       devm_kfree(dev, dma);
+       dev_info(dev, "can't use DMA\n");
+
+       return NULL;
+}
+
+void stm32_i2c_dma_free(struct stm32_i2c_dma *dma)
+{
+       dma->dma_buf = 0;
+       dma->dma_len = 0;
+
+       dma_release_channel(dma->chan_tx);
+       dma->chan_tx = NULL;
+
+       dma_release_channel(dma->chan_rx);
+       dma->chan_rx = NULL;
+
+       dma->chan_using = NULL;
+}
+
+int stm32_i2c_prep_dma_xfer(struct device *dev, struct stm32_i2c_dma *dma,
+                           bool rd_wr, u32 len, u8 *buf,
+                           dma_async_tx_callback callback,
+                           void *dma_async_param)
+{
+       struct dma_async_tx_descriptor *txdesc;
+       struct device *chan_dev;
+       int ret;
+
+       if (rd_wr) {
+               dma->chan_using = dma->chan_rx;
+               dma->dma_transfer_dir = DMA_DEV_TO_MEM;
+               dma->dma_data_dir = DMA_FROM_DEVICE;
+       } else {
+               dma->chan_using = dma->chan_tx;
+               dma->dma_transfer_dir = DMA_MEM_TO_DEV;
+               dma->dma_data_dir = DMA_TO_DEVICE;
+       }
+
+       dma->dma_len = len;
+       chan_dev = dma->chan_using->device->dev;
+
+       dma->dma_buf = dma_map_single(chan_dev, buf, dma->dma_len,
+                                     dma->dma_data_dir);
+       if (dma_mapping_error(chan_dev, dma->dma_buf)) {
+               dev_err(dev, "DMA mapping failed\n");
+               return -EINVAL;
+       }
+
+       txdesc = dmaengine_prep_slave_single(dma->chan_using, dma->dma_buf,
+                                            dma->dma_len,
+                                            dma->dma_transfer_dir,
+                                            DMA_PREP_INTERRUPT);
+       if (!txdesc) {
+               dev_err(dev, "Not able to get desc for DMA xfer\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       reinit_completion(&dma->dma_complete);
+
+       txdesc->callback = callback;
+       txdesc->callback_param = dma_async_param;
+       ret = dma_submit_error(dmaengine_submit(txdesc));
+       if (ret < 0) {
+               dev_err(dev, "DMA submit failed\n");
+               goto err;
+       }
+
+       dma_async_issue_pending(dma->chan_using);
+
+       return 0;
+
+err:
+       dma_unmap_single(chan_dev, dma->dma_buf, dma->dma_len,
+                        dma->dma_data_dir);
+       return ret;
+}
index d4f9cef..868755f 100644 (file)
 #ifndef _I2C_STM32_H
 #define _I2C_STM32_H
 
+#include <linux/dma-direction.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+
 enum stm32_i2c_speed {
        STM32_I2C_SPEED_STANDARD, /* 100 kHz */
        STM32_I2C_SPEED_FAST, /* 400 kHz */
@@ -18,4 +22,37 @@ enum stm32_i2c_speed {
        STM32_I2C_SPEED_END,
 };
 
+/**
+ * struct stm32_i2c_dma - DMA specific data
+ * @chan_tx: dma channel for TX transfer
+ * @chan_rx: dma channel for RX transfer
+ * @chan_using: dma channel used for the current transfer (TX or RX)
+ * @dma_buf: dma buffer
+ * @dma_len: dma buffer len
+ * @dma_transfer_dir: dma transfer direction indicator
+ * @dma_data_dir: dma transfer mode indicator
+ * @dma_complete: dma transfer completion
+ */
+struct stm32_i2c_dma {
+       struct dma_chan *chan_tx;
+       struct dma_chan *chan_rx;
+       struct dma_chan *chan_using;
+       dma_addr_t dma_buf;
+       unsigned int dma_len;
+       enum dma_transfer_direction dma_transfer_dir;
+       enum dma_data_direction dma_data_dir;
+       struct completion dma_complete;
+};
+
+struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev,
+                                           dma_addr_t phy_addr,
+                                           u32 txdr_offset, u32 rxdr_offset);
+
+void stm32_i2c_dma_free(struct stm32_i2c_dma *dma);
+
+int stm32_i2c_prep_dma_xfer(struct device *dev, struct stm32_i2c_dma *dma,
+                           bool rd_wr, u32 len, u8 *buf,
+                           dma_async_tx_callback callback,
+                           void *dma_async_param);
+
 #endif /* _I2C_STM32_H */
index f273e28..62d023e 100644 (file)
@@ -35,6 +35,9 @@
 /* STM32F7 I2C registers */
 #define STM32F7_I2C_CR1                                0x00
 #define STM32F7_I2C_CR2                                0x04
+#define STM32F7_I2C_OAR1                       0x08
+#define STM32F7_I2C_OAR2                       0x0C
+#define STM32F7_I2C_PECR                       0x20
 #define STM32F7_I2C_TIMINGR                    0x10
 #define STM32F7_I2C_ISR                                0x18
 #define STM32F7_I2C_ICR                                0x1C
 #define STM32F7_I2C_TXDR                       0x28
 
 /* STM32F7 I2C control 1 */
+#define STM32F7_I2C_CR1_PECEN                  BIT(23)
+#define STM32F7_I2C_CR1_SBC                    BIT(16)
+#define STM32F7_I2C_CR1_RXDMAEN                        BIT(15)
+#define STM32F7_I2C_CR1_TXDMAEN                        BIT(14)
 #define STM32F7_I2C_CR1_ANFOFF                 BIT(12)
 #define STM32F7_I2C_CR1_ERRIE                  BIT(7)
 #define STM32F7_I2C_CR1_TCIE                   BIT(6)
                                                | STM32F7_I2C_CR1_NACKIE \
                                                | STM32F7_I2C_CR1_RXIE \
                                                | STM32F7_I2C_CR1_TXIE)
+#define STM32F7_I2C_XFER_IRQ_MASK              (STM32F7_I2C_CR1_TCIE \
+                                               | STM32F7_I2C_CR1_STOPIE \
+                                               | STM32F7_I2C_CR1_NACKIE \
+                                               | STM32F7_I2C_CR1_RXIE \
+                                               | STM32F7_I2C_CR1_TXIE)
 
 /* STM32F7 I2C control 2 */
+#define STM32F7_I2C_CR2_PECBYTE                        BIT(26)
 #define STM32F7_I2C_CR2_RELOAD                 BIT(24)
 #define STM32F7_I2C_CR2_NBYTES_MASK            GENMASK(23, 16)
 #define STM32F7_I2C_CR2_NBYTES(n)              (((n) & 0xff) << 16)
 #define STM32F7_I2C_CR2_NACK                   BIT(15)
 #define STM32F7_I2C_CR2_STOP                   BIT(14)
 #define STM32F7_I2C_CR2_START                  BIT(13)
+#define STM32F7_I2C_CR2_HEAD10R                        BIT(12)
+#define STM32F7_I2C_CR2_ADD10                  BIT(11)
 #define STM32F7_I2C_CR2_RD_WRN                 BIT(10)
+#define STM32F7_I2C_CR2_SADD10_MASK            GENMASK(9, 0)
+#define STM32F7_I2C_CR2_SADD10(n)              (((n) & \
+                                               STM32F7_I2C_CR2_SADD10_MASK))
 #define STM32F7_I2C_CR2_SADD7_MASK             GENMASK(7, 1)
 #define STM32F7_I2C_CR2_SADD7(n)               (((n) & 0x7f) << 1)
 
+/* STM32F7 I2C Own Address 1 */
+#define STM32F7_I2C_OAR1_OA1EN                 BIT(15)
+#define STM32F7_I2C_OAR1_OA1MODE               BIT(10)
+#define STM32F7_I2C_OAR1_OA1_10_MASK           GENMASK(9, 0)
+#define STM32F7_I2C_OAR1_OA1_10(n)             (((n) & \
+                                               STM32F7_I2C_OAR1_OA1_10_MASK))
+#define STM32F7_I2C_OAR1_OA1_7_MASK            GENMASK(7, 1)
+#define STM32F7_I2C_OAR1_OA1_7(n)              (((n) & 0x7f) << 1)
+#define STM32F7_I2C_OAR1_MASK                  (STM32F7_I2C_OAR1_OA1_7_MASK \
+                                               | STM32F7_I2C_OAR1_OA1_10_MASK \
+                                               | STM32F7_I2C_OAR1_OA1EN \
+                                               | STM32F7_I2C_OAR1_OA1MODE)
+
+/* STM32F7 I2C Own Address 2 */
+#define STM32F7_I2C_OAR2_OA2EN                 BIT(15)
+#define STM32F7_I2C_OAR2_OA2MSK_MASK           GENMASK(10, 8)
+#define STM32F7_I2C_OAR2_OA2MSK(n)             (((n) & 0x7) << 8)
+#define STM32F7_I2C_OAR2_OA2_7_MASK            GENMASK(7, 1)
+#define STM32F7_I2C_OAR2_OA2_7(n)              (((n) & 0x7f) << 1)
+#define STM32F7_I2C_OAR2_MASK                  (STM32F7_I2C_OAR2_OA2MSK_MASK \
+                                               | STM32F7_I2C_OAR2_OA2_7_MASK \
+                                               | STM32F7_I2C_OAR2_OA2EN)
+
 /* STM32F7 I2C Interrupt Status */
+#define STM32F7_I2C_ISR_ADDCODE_MASK           GENMASK(23, 17)
+#define STM32F7_I2C_ISR_ADDCODE_GET(n) \
+                               (((n) & STM32F7_I2C_ISR_ADDCODE_MASK) >> 17)
+#define STM32F7_I2C_ISR_DIR                    BIT(16)
 #define STM32F7_I2C_ISR_BUSY                   BIT(15)
+#define STM32F7_I2C_ISR_PECERR                 BIT(11)
 #define STM32F7_I2C_ISR_ARLO                   BIT(9)
 #define STM32F7_I2C_ISR_BERR                   BIT(8)
 #define STM32F7_I2C_ISR_TCR                    BIT(7)
 #define STM32F7_I2C_ISR_TC                     BIT(6)
 #define STM32F7_I2C_ISR_STOPF                  BIT(5)
 #define STM32F7_I2C_ISR_NACKF                  BIT(4)
+#define STM32F7_I2C_ISR_ADDR                   BIT(3)
 #define STM32F7_I2C_ISR_RXNE                   BIT(2)
 #define STM32F7_I2C_ISR_TXIS                   BIT(1)
+#define STM32F7_I2C_ISR_TXE                    BIT(0)
 
 /* STM32F7 I2C Interrupt Clear */
+#define STM32F7_I2C_ICR_PECCF                  BIT(11)
 #define STM32F7_I2C_ICR_ARLOCF                 BIT(9)
 #define STM32F7_I2C_ICR_BERRCF                 BIT(8)
 #define STM32F7_I2C_ICR_STOPCF                 BIT(5)
 #define STM32F7_I2C_ICR_NACKCF                 BIT(4)
+#define STM32F7_I2C_ICR_ADDRCF                 BIT(3)
 
 /* STM32F7 I2C Timing */
 #define STM32F7_I2C_TIMINGR_PRESC(n)           (((n) & 0xf) << 28)
 #define STM32F7_I2C_TIMINGR_SCLL(n)            ((n) & 0xff)
 
 #define STM32F7_I2C_MAX_LEN                    0xff
+#define STM32F7_I2C_DMA_LEN_MIN                        0x16
+#define STM32F7_I2C_MAX_SLAVE                  0x2
 
 #define STM32F7_I2C_DNF_DEFAULT                        0
 #define STM32F7_I2C_DNF_MAX                    16
@@ -159,11 +211,12 @@ struct stm32f7_i2c_setup {
 
 /**
  * struct stm32f7_i2c_timings - private I2C output parameters
- * @prec: Prescaler value
+ * @node: List entry
+ * @presc: Prescaler value
  * @scldel: Data setup time
  * @sdadel: Data hold time
  * @sclh: SCL high period (master mode)
- * @sclh: SCL low period (master mode)
+ * @scll: SCL low period (master mode)
  */
 struct stm32f7_i2c_timings {
        struct list_head node;
@@ -176,18 +229,30 @@ struct stm32f7_i2c_timings {
 
 /**
  * struct stm32f7_i2c_msg - client specific data
- * @addr: 8-bit slave addr, including r/w bit
+ * @addr: 8-bit or 10-bit slave addr, including r/w bit
  * @count: number of bytes to be transferred
  * @buf: data buffer
  * @result: result of the transfer
  * @stop: last I2C msg to be sent, i.e. STOP to be generated
+ * @smbus: boolean to know if the I2C IP is used in SMBus mode
+ * @size: type of SMBus protocol
+ * @read_write: direction of SMBus protocol
+ * SMBus block read and SMBus block write - block read process call protocols
+ * @smbus_buf: buffer to be used for SMBus protocol transfer. It will
+ * contain a maximum of 32 bytes of data + byte command + byte count + PEC
+ * This buffer has to be 32-bit aligned to be compliant with memory address
+ * register in DMA mode.
  */
 struct stm32f7_i2c_msg {
-       u8 addr;
+       u16 addr;
        u32 count;
        u8 *buf;
        int result;
        bool stop;
+       bool smbus;
+       int size;
+       char read_write;
+       u8 smbus_buf[I2C_SMBUS_BLOCK_MAX + 3] __aligned(4);
 };
 
 /**
@@ -204,6 +269,13 @@ struct stm32f7_i2c_msg {
  * @f7_msg: customized i2c msg for driver usage
  * @setup: I2C timing input setup
  * @timing: I2C computed timings
+ * @slave: list of slave devices registered on the I2C bus
+ * @slave_running: slave device currently used
+ * @slave_dir: transfer direction for the current slave device
+ * @master_mode: boolean to know in which mode the I2C is running (master or
+ * slave)
+ * @dma: dma data
+ * @use_dma: boolean to know if dma is used in the current transfer
  */
 struct stm32f7_i2c_dev {
        struct i2c_adapter adap;
@@ -218,6 +290,12 @@ struct stm32f7_i2c_dev {
        struct stm32f7_i2c_msg f7_msg;
        struct stm32f7_i2c_setup setup;
        struct stm32f7_i2c_timings timing;
+       struct i2c_client *slave[STM32F7_I2C_MAX_SLAVE];
+       struct i2c_client *slave_running;
+       u32 slave_dir;
+       bool master_mode;
+       struct stm32_i2c_dma *dma;
+       bool use_dma;
 };
 
 /**
@@ -283,6 +361,11 @@ static inline void stm32f7_i2c_clr_bits(void __iomem *reg, u32 mask)
        writel_relaxed(readl_relaxed(reg) & ~mask, reg);
 }
 
+static void stm32f7_i2c_disable_irq(struct stm32f7_i2c_dev *i2c_dev, u32 mask)
+{
+       stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1, mask);
+}
+
 static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev,
                                      struct stm32f7_i2c_setup *setup,
                                      struct stm32f7_i2c_timings *output)
@@ -524,6 +607,25 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,
        return 0;
 }
 
+static void stm32f7_i2c_disable_dma_req(struct stm32f7_i2c_dev *i2c_dev)
+{
+       void __iomem *base = i2c_dev->base;
+       u32 mask = STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN;
+
+       stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, mask);
+}
+
+static void stm32f7_i2c_dma_callback(void *arg)
+{
+       struct stm32f7_i2c_dev *i2c_dev = (struct stm32f7_i2c_dev *)arg;
+       struct stm32_i2c_dma *dma = i2c_dev->dma;
+       struct device *dev = dma->chan_using->device->dev;
+
+       stm32f7_i2c_disable_dma_req(i2c_dev);
+       dma_unmap_single(dev, dma->dma_buf, dma->dma_len, dma->dma_data_dir);
+       complete(&dma->dma_complete);
+}
+
 static void stm32f7_i2c_hw_config(struct stm32f7_i2c_dev *i2c_dev)
 {
        struct stm32f7_i2c_timings *t = &i2c_dev->timing;
@@ -567,6 +669,9 @@ static void stm32f7_i2c_read_rx_data(struct stm32f7_i2c_dev *i2c_dev)
        if (f7_msg->count) {
                *f7_msg->buf++ = readb_relaxed(base + STM32F7_I2C_RXDR);
                f7_msg->count--;
+       } else {
+               /* Flush RX buffer has no data is expected */
+               readb_relaxed(base + STM32F7_I2C_RXDR);
        }
 }
 
@@ -575,6 +680,9 @@ static void stm32f7_i2c_reload(struct stm32f7_i2c_dev *i2c_dev)
        struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
        u32 cr2;
 
+       if (i2c_dev->use_dma)
+               f7_msg->count -= STM32F7_I2C_MAX_LEN;
+
        cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2);
 
        cr2 &= ~STM32F7_I2C_CR2_NBYTES_MASK;
@@ -588,6 +696,43 @@ static void stm32f7_i2c_reload(struct stm32f7_i2c_dev *i2c_dev)
        writel_relaxed(cr2, i2c_dev->base + STM32F7_I2C_CR2);
 }
 
+static void stm32f7_i2c_smbus_reload(struct stm32f7_i2c_dev *i2c_dev)
+{
+       struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
+       u32 cr2;
+       u8 *val;
+
+       /*
+        * For I2C_SMBUS_BLOCK_DATA && I2C_SMBUS_BLOCK_PROC_CALL, the first
+        * data received inform us how many data will follow.
+        */
+       stm32f7_i2c_read_rx_data(i2c_dev);
+
+       /*
+        * Update NBYTES with the value read to continue the transfer
+        */
+       val = f7_msg->buf - sizeof(u8);
+       f7_msg->count = *val;
+       cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2);
+       cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK | STM32F7_I2C_CR2_RELOAD);
+       cr2 |= STM32F7_I2C_CR2_NBYTES(f7_msg->count);
+       writel_relaxed(cr2, i2c_dev->base + STM32F7_I2C_CR2);
+}
+
+static int stm32f7_i2c_release_bus(struct i2c_adapter *i2c_adap)
+{
+       struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
+
+       dev_info(i2c_dev->dev, "Trying to recover bus\n");
+
+       stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1,
+                            STM32F7_I2C_CR1_PE);
+
+       stm32f7_i2c_hw_config(i2c_dev);
+
+       return 0;
+}
+
 static int stm32f7_i2c_wait_free_bus(struct stm32f7_i2c_dev *i2c_dev)
 {
        u32 status;
@@ -597,12 +742,18 @@ static int stm32f7_i2c_wait_free_bus(struct stm32f7_i2c_dev *i2c_dev)
                                         status,
                                         !(status & STM32F7_I2C_ISR_BUSY),
                                         10, 1000);
+       if (!ret)
+               return 0;
+
+       dev_info(i2c_dev->dev, "bus busy\n");
+
+       ret = stm32f7_i2c_release_bus(&i2c_dev->adap);
        if (ret) {
-               dev_dbg(i2c_dev->dev, "bus busy\n");
-               ret = -EBUSY;
+               dev_err(i2c_dev->dev, "Failed to recover the bus (%d)\n", ret);
+               return ret;
        }
 
-       return ret;
+       return -EBUSY;
 }
 
 static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
@@ -611,6 +762,7 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
        struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
        void __iomem *base = i2c_dev->base;
        u32 cr1, cr2;
+       int ret;
 
        f7_msg->addr = msg->addr;
        f7_msg->buf = msg->buf;
@@ -629,8 +781,15 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
                cr2 |= STM32F7_I2C_CR2_RD_WRN;
 
        /* Set slave address */
-       cr2 &= ~STM32F7_I2C_CR2_SADD7_MASK;
-       cr2 |= STM32F7_I2C_CR2_SADD7(f7_msg->addr);
+       cr2 &= ~(STM32F7_I2C_CR2_HEAD10R | STM32F7_I2C_CR2_ADD10);
+       if (msg->flags & I2C_M_TEN) {
+               cr2 &= ~STM32F7_I2C_CR2_SADD10_MASK;
+               cr2 |= STM32F7_I2C_CR2_SADD10(f7_msg->addr);
+               cr2 |= STM32F7_I2C_CR2_ADD10;
+       } else {
+               cr2 &= ~STM32F7_I2C_CR2_SADD7_MASK;
+               cr2 |= STM32F7_I2C_CR2_SADD7(f7_msg->addr);
+       }
 
        /* Set nb bytes to transfer and reload if needed */
        cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK | STM32F7_I2C_CR2_RELOAD);
@@ -645,16 +804,286 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
        cr1 |= STM32F7_I2C_CR1_ERRIE | STM32F7_I2C_CR1_TCIE |
                STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE;
 
-       /* Clear TX/RX interrupt */
+       /* Clear DMA req and TX/RX interrupt */
+       cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE |
+                       STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN);
+
+       /* Configure DMA or enable RX/TX interrupt */
+       i2c_dev->use_dma = false;
+       if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN) {
+               ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
+                                             msg->flags & I2C_M_RD,
+                                             f7_msg->count, f7_msg->buf,
+                                             stm32f7_i2c_dma_callback,
+                                             i2c_dev);
+               if (!ret)
+                       i2c_dev->use_dma = true;
+               else
+                       dev_warn(i2c_dev->dev, "can't use DMA\n");
+       }
+
+       if (!i2c_dev->use_dma) {
+               if (msg->flags & I2C_M_RD)
+                       cr1 |= STM32F7_I2C_CR1_RXIE;
+               else
+                       cr1 |= STM32F7_I2C_CR1_TXIE;
+       } else {
+               if (msg->flags & I2C_M_RD)
+                       cr1 |= STM32F7_I2C_CR1_RXDMAEN;
+               else
+                       cr1 |= STM32F7_I2C_CR1_TXDMAEN;
+       }
+
+       /* Configure Start/Repeated Start */
+       cr2 |= STM32F7_I2C_CR2_START;
+
+       i2c_dev->master_mode = true;
+
+       /* Write configurations registers */
+       writel_relaxed(cr1, base + STM32F7_I2C_CR1);
+       writel_relaxed(cr2, base + STM32F7_I2C_CR2);
+}
+
+static int stm32f7_i2c_smbus_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
+                                     unsigned short flags, u8 command,
+                                     union i2c_smbus_data *data)
+{
+       struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
+       struct device *dev = i2c_dev->dev;
+       void __iomem *base = i2c_dev->base;
+       u32 cr1, cr2;
+       int i, ret;
+
+       f7_msg->result = 0;
+       reinit_completion(&i2c_dev->complete);
+
+       cr2 = readl_relaxed(base + STM32F7_I2C_CR2);
+       cr1 = readl_relaxed(base + STM32F7_I2C_CR1);
+
+       /* Set transfer direction */
+       cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
+       if (f7_msg->read_write)
+               cr2 |= STM32F7_I2C_CR2_RD_WRN;
+
+       /* Set slave address */
+       cr2 &= ~(STM32F7_I2C_CR2_ADD10 | STM32F7_I2C_CR2_SADD7_MASK);
+       cr2 |= STM32F7_I2C_CR2_SADD7(f7_msg->addr);
+
+       f7_msg->smbus_buf[0] = command;
+       switch (f7_msg->size) {
+       case I2C_SMBUS_QUICK:
+               f7_msg->stop = true;
+               f7_msg->count = 0;
+               break;
+       case I2C_SMBUS_BYTE:
+               f7_msg->stop = true;
+               f7_msg->count = 1;
+               break;
+       case I2C_SMBUS_BYTE_DATA:
+               if (f7_msg->read_write) {
+                       f7_msg->stop = false;
+                       f7_msg->count = 1;
+                       cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
+               } else {
+                       f7_msg->stop = true;
+                       f7_msg->count = 2;
+                       f7_msg->smbus_buf[1] = data->byte;
+               }
+               break;
+       case I2C_SMBUS_WORD_DATA:
+               if (f7_msg->read_write) {
+                       f7_msg->stop = false;
+                       f7_msg->count = 1;
+                       cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
+               } else {
+                       f7_msg->stop = true;
+                       f7_msg->count = 3;
+                       f7_msg->smbus_buf[1] = data->word & 0xff;
+                       f7_msg->smbus_buf[2] = data->word >> 8;
+               }
+               break;
+       case I2C_SMBUS_BLOCK_DATA:
+               if (f7_msg->read_write) {
+                       f7_msg->stop = false;
+                       f7_msg->count = 1;
+                       cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
+               } else {
+                       f7_msg->stop = true;
+                       if (data->block[0] > I2C_SMBUS_BLOCK_MAX ||
+                           !data->block[0]) {
+                               dev_err(dev, "Invalid block write size %d\n",
+                                       data->block[0]);
+                               return -EINVAL;
+                       }
+                       f7_msg->count = data->block[0] + 2;
+                       for (i = 1; i < f7_msg->count; i++)
+                               f7_msg->smbus_buf[i] = data->block[i - 1];
+               }
+               break;
+       case I2C_SMBUS_PROC_CALL:
+               f7_msg->stop = false;
+               f7_msg->count = 3;
+               f7_msg->smbus_buf[1] = data->word & 0xff;
+               f7_msg->smbus_buf[2] = data->word >> 8;
+               cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
+               f7_msg->read_write = I2C_SMBUS_READ;
+               break;
+       case I2C_SMBUS_BLOCK_PROC_CALL:
+               f7_msg->stop = false;
+               if (data->block[0] > I2C_SMBUS_BLOCK_MAX - 1) {
+                       dev_err(dev, "Invalid block write size %d\n",
+                               data->block[0]);
+                       return -EINVAL;
+               }
+               f7_msg->count = data->block[0] + 2;
+               for (i = 1; i < f7_msg->count; i++)
+                       f7_msg->smbus_buf[i] = data->block[i - 1];
+               cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
+               f7_msg->read_write = I2C_SMBUS_READ;
+               break;
+       default:
+               dev_err(dev, "Unsupported smbus protocol %d\n", f7_msg->size);
+               return -EOPNOTSUPP;
+       }
+
+       f7_msg->buf = f7_msg->smbus_buf;
+
+       /* Configure PEC */
+       if ((flags & I2C_CLIENT_PEC) && f7_msg->size != I2C_SMBUS_QUICK) {
+               cr1 |= STM32F7_I2C_CR1_PECEN;
+               cr2 |= STM32F7_I2C_CR2_PECBYTE;
+               if (!f7_msg->read_write)
+                       f7_msg->count++;
+       } else {
+               cr1 &= ~STM32F7_I2C_CR1_PECEN;
+               cr2 &= ~STM32F7_I2C_CR2_PECBYTE;
+       }
+
+       /* Set number of bytes to be transferred */
+       cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK | STM32F7_I2C_CR2_RELOAD);
+       cr2 |= STM32F7_I2C_CR2_NBYTES(f7_msg->count);
+
+       /* Enable NACK, STOP, error and transfer complete interrupts */
+       cr1 |= STM32F7_I2C_CR1_ERRIE | STM32F7_I2C_CR1_TCIE |
+               STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE;
+
+       /* Clear DMA req and TX/RX interrupt */
+       cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE |
+                       STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN);
+
+       /* Configure DMA or enable RX/TX interrupt */
+       i2c_dev->use_dma = false;
+       if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN) {
+               ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
+                                             cr2 & STM32F7_I2C_CR2_RD_WRN,
+                                             f7_msg->count, f7_msg->buf,
+                                             stm32f7_i2c_dma_callback,
+                                             i2c_dev);
+               if (!ret)
+                       i2c_dev->use_dma = true;
+               else
+                       dev_warn(i2c_dev->dev, "can't use DMA\n");
+       }
+
+       if (!i2c_dev->use_dma) {
+               if (cr2 & STM32F7_I2C_CR2_RD_WRN)
+                       cr1 |= STM32F7_I2C_CR1_RXIE;
+               else
+                       cr1 |= STM32F7_I2C_CR1_TXIE;
+       } else {
+               if (cr2 & STM32F7_I2C_CR2_RD_WRN)
+                       cr1 |= STM32F7_I2C_CR1_RXDMAEN;
+               else
+                       cr1 |= STM32F7_I2C_CR1_TXDMAEN;
+       }
+
+       /* Set Start bit */
+       cr2 |= STM32F7_I2C_CR2_START;
+
+       i2c_dev->master_mode = true;
+
+       /* Write configurations registers */
+       writel_relaxed(cr1, base + STM32F7_I2C_CR1);
+       writel_relaxed(cr2, base + STM32F7_I2C_CR2);
+
+       return 0;
+}
+
+static void stm32f7_i2c_smbus_rep_start(struct stm32f7_i2c_dev *i2c_dev)
+{
+       struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
+       void __iomem *base = i2c_dev->base;
+       u32 cr1, cr2;
+       int ret;
+
+       cr2 = readl_relaxed(base + STM32F7_I2C_CR2);
+       cr1 = readl_relaxed(base + STM32F7_I2C_CR1);
+
+       /* Set transfer direction */
+       cr2 |= STM32F7_I2C_CR2_RD_WRN;
+
+       switch (f7_msg->size) {
+       case I2C_SMBUS_BYTE_DATA:
+               f7_msg->count = 1;
+               break;
+       case I2C_SMBUS_WORD_DATA:
+       case I2C_SMBUS_PROC_CALL:
+               f7_msg->count = 2;
+               break;
+       case I2C_SMBUS_BLOCK_DATA:
+       case I2C_SMBUS_BLOCK_PROC_CALL:
+               f7_msg->count = 1;
+               cr2 |= STM32F7_I2C_CR2_RELOAD;
+               break;
+       }
+
+       f7_msg->buf = f7_msg->smbus_buf;
+       f7_msg->stop = true;
+
+       /* Add one byte for PEC if needed */
+       if (cr1 & STM32F7_I2C_CR1_PECEN)
+               f7_msg->count++;
+
+       /* Set number of bytes to be transferred */
+       cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK);
+       cr2 |= STM32F7_I2C_CR2_NBYTES(f7_msg->count);
+
+       /*
+        * Configure RX/TX interrupt:
+        */
        cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE);
+       cr1 |= STM32F7_I2C_CR1_RXIE;
 
-       /* Enable RX/TX interrupt according to msg direction */
-       if (msg->flags & I2C_M_RD)
+       /*
+        * Configure DMA or enable RX/TX interrupt:
+        * For I2C_SMBUS_BLOCK_DATA and I2C_SMBUS_BLOCK_PROC_CALL we don't use
+        * dma as we don't know in advance how many data will be received
+        */
+       cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE |
+                STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN);
+
+       i2c_dev->use_dma = false;
+       if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN &&
+           f7_msg->size != I2C_SMBUS_BLOCK_DATA &&
+           f7_msg->size != I2C_SMBUS_BLOCK_PROC_CALL) {
+               ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
+                                             cr2 & STM32F7_I2C_CR2_RD_WRN,
+                                             f7_msg->count, f7_msg->buf,
+                                             stm32f7_i2c_dma_callback,
+                                             i2c_dev);
+
+               if (!ret)
+                       i2c_dev->use_dma = true;
+               else
+                       dev_warn(i2c_dev->dev, "can't use DMA\n");
+       }
+
+       if (!i2c_dev->use_dma)
                cr1 |= STM32F7_I2C_CR1_RXIE;
        else
-               cr1 |= STM32F7_I2C_CR1_TXIE;
+               cr1 |= STM32F7_I2C_CR1_RXDMAEN;
 
-       /* Configure Start/Repeated Start */
+       /* Configure Repeated Start */
        cr2 |= STM32F7_I2C_CR2_START;
 
        /* Write configurations registers */
@@ -662,9 +1091,278 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
        writel_relaxed(cr2, base + STM32F7_I2C_CR2);
 }
 
-static void stm32f7_i2c_disable_irq(struct stm32f7_i2c_dev *i2c_dev, u32 mask)
+static int stm32f7_i2c_smbus_check_pec(struct stm32f7_i2c_dev *i2c_dev)
 {
-       stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1, mask);
+       struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
+       u8 count, internal_pec, received_pec;
+
+       internal_pec = readl_relaxed(i2c_dev->base + STM32F7_I2C_PECR);
+
+       switch (f7_msg->size) {
+       case I2C_SMBUS_BYTE:
+       case I2C_SMBUS_BYTE_DATA:
+               received_pec = f7_msg->smbus_buf[1];
+               break;
+       case I2C_SMBUS_WORD_DATA:
+       case I2C_SMBUS_PROC_CALL:
+               received_pec = f7_msg->smbus_buf[2];
+               break;
+       case I2C_SMBUS_BLOCK_DATA:
+       case I2C_SMBUS_BLOCK_PROC_CALL:
+               count = f7_msg->smbus_buf[0];
+               received_pec = f7_msg->smbus_buf[count];
+               break;
+       default:
+               dev_err(i2c_dev->dev, "Unsupported smbus protocol for PEC\n");
+               return -EINVAL;
+       }
+
+       if (internal_pec != received_pec) {
+               dev_err(i2c_dev->dev, "Bad PEC 0x%02x vs. 0x%02x\n",
+                       internal_pec, received_pec);
+               return -EBADMSG;
+       }
+
+       return 0;
+}
+
+static bool stm32f7_i2c_is_addr_match(struct i2c_client *slave, u32 addcode)
+{
+       u32 addr;
+
+       if (!slave)
+               return false;
+
+       if (slave->flags & I2C_CLIENT_TEN) {
+               /*
+                * For 10-bit addr, addcode = 11110XY with
+                * X = Bit 9 of slave address
+                * Y = Bit 8 of slave address
+                */
+               addr = slave->addr >> 8;
+               addr |= 0x78;
+               if (addr == addcode)
+                       return true;
+       } else {
+               addr = slave->addr & 0x7f;
+               if (addr == addcode)
+                       return true;
+       }
+
+       return false;
+}
+
+static void stm32f7_i2c_slave_start(struct stm32f7_i2c_dev *i2c_dev)
+{
+       struct i2c_client *slave = i2c_dev->slave_running;
+       void __iomem *base = i2c_dev->base;
+       u32 mask;
+       u8 value = 0;
+
+       if (i2c_dev->slave_dir) {
+               /* Notify i2c slave that new read transfer is starting */
+               i2c_slave_event(slave, I2C_SLAVE_READ_REQUESTED, &value);
+
+               /*
+                * Disable slave TX config in case of I2C combined message
+                * (I2C Write followed by I2C Read)
+                */
+               mask = STM32F7_I2C_CR2_RELOAD;
+               stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR2, mask);
+               mask = STM32F7_I2C_CR1_SBC | STM32F7_I2C_CR1_RXIE |
+                      STM32F7_I2C_CR1_TCIE;
+               stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, mask);
+
+               /* Enable TX empty, STOP, NACK interrupts */
+               mask =  STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE |
+                       STM32F7_I2C_CR1_TXIE;
+               stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
+
+       } else {
+               /* Notify i2c slave that new write transfer is starting */
+               i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value);
+
+               /* Set reload mode to be able to ACK/NACK each received byte */
+               mask = STM32F7_I2C_CR2_RELOAD;
+               stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
+
+               /*
+                * Set STOP, NACK, RX empty and transfer complete interrupts.*
+                * Set Slave Byte Control to be able to ACK/NACK each data
+                * byte received
+                */
+               mask =  STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE |
+                       STM32F7_I2C_CR1_SBC | STM32F7_I2C_CR1_RXIE |
+                       STM32F7_I2C_CR1_TCIE;
+               stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
+       }
+}
+
+static void stm32f7_i2c_slave_addr(struct stm32f7_i2c_dev *i2c_dev)
+{
+       void __iomem *base = i2c_dev->base;
+       u32 isr, addcode, dir, mask;
+       int i;
+
+       isr = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
+       addcode = STM32F7_I2C_ISR_ADDCODE_GET(isr);
+       dir = isr & STM32F7_I2C_ISR_DIR;
+
+       for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
+               if (stm32f7_i2c_is_addr_match(i2c_dev->slave[i], addcode)) {
+                       i2c_dev->slave_running = i2c_dev->slave[i];
+                       i2c_dev->slave_dir = dir;
+
+                       /* Start I2C slave processing */
+                       stm32f7_i2c_slave_start(i2c_dev);
+
+                       /* Clear ADDR flag */
+                       mask = STM32F7_I2C_ICR_ADDRCF;
+                       writel_relaxed(mask, base + STM32F7_I2C_ICR);
+                       break;
+               }
+       }
+}
+
+static int stm32f7_i2c_get_slave_id(struct stm32f7_i2c_dev *i2c_dev,
+                                   struct i2c_client *slave, int *id)
+{
+       int i;
+
+       for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
+               if (i2c_dev->slave[i] == slave) {
+                       *id = i;
+                       return 0;
+               }
+       }
+
+       dev_err(i2c_dev->dev, "Slave 0x%x not registered\n", slave->addr);
+
+       return -ENODEV;
+}
+
+static int stm32f7_i2c_get_free_slave_id(struct stm32f7_i2c_dev *i2c_dev,
+                                        struct i2c_client *slave, int *id)
+{
+       struct device *dev = i2c_dev->dev;
+       int i;
+
+       /*
+        * slave[0] supports 7-bit and 10-bit slave address
+        * slave[1] supports 7-bit slave address only
+        */
+       for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
+               if (i == 1 && (slave->flags & I2C_CLIENT_PEC))
+                       continue;
+               if (!i2c_dev->slave[i]) {
+                       *id = i;
+                       return 0;
+               }
+       }
+
+       dev_err(dev, "Slave 0x%x could not be registered\n", slave->addr);
+
+       return -EINVAL;
+}
+
+static bool stm32f7_i2c_is_slave_registered(struct stm32f7_i2c_dev *i2c_dev)
+{
+       int i;
+
+       for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
+               if (i2c_dev->slave[i])
+                       return true;
+       }
+
+       return false;
+}
+
+static bool stm32f7_i2c_is_slave_busy(struct stm32f7_i2c_dev *i2c_dev)
+{
+       int i, busy;
+
+       busy = 0;
+       for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
+               if (i2c_dev->slave[i])
+                       busy++;
+       }
+
+       return i == busy;
+}
+
+static irqreturn_t stm32f7_i2c_slave_isr_event(struct stm32f7_i2c_dev *i2c_dev)
+{
+       void __iomem *base = i2c_dev->base;
+       u32 cr2, status, mask;
+       u8 val;
+       int ret;
+
+       status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
+
+       /* Slave transmitter mode */
+       if (status & STM32F7_I2C_ISR_TXIS) {
+               i2c_slave_event(i2c_dev->slave_running,
+                               I2C_SLAVE_READ_PROCESSED,
+                               &val);
+
+               /* Write data byte */
+               writel_relaxed(val, base + STM32F7_I2C_TXDR);
+       }
+
+       /* Transfer Complete Reload for Slave receiver mode */
+       if (status & STM32F7_I2C_ISR_TCR || status & STM32F7_I2C_ISR_RXNE) {
+               /*
+                * Read data byte then set NBYTES to receive next byte or NACK
+                * the current received byte
+                */
+               val = readb_relaxed(i2c_dev->base + STM32F7_I2C_RXDR);
+               ret = i2c_slave_event(i2c_dev->slave_running,
+                                     I2C_SLAVE_WRITE_RECEIVED,
+                                     &val);
+               if (!ret) {
+                       cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2);
+                       cr2 |= STM32F7_I2C_CR2_NBYTES(1);
+                       writel_relaxed(cr2, i2c_dev->base + STM32F7_I2C_CR2);
+               } else {
+                       mask = STM32F7_I2C_CR2_NACK;
+                       stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
+               }
+       }
+
+       /* NACK received */
+       if (status & STM32F7_I2C_ISR_NACKF) {
+               dev_dbg(i2c_dev->dev, "<%s>: Receive NACK\n", __func__);
+               writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR);
+       }
+
+       /* STOP received */
+       if (status & STM32F7_I2C_ISR_STOPF) {
+               /* Disable interrupts */
+               stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_XFER_IRQ_MASK);
+
+               if (i2c_dev->slave_dir) {
+                       /*
+                        * Flush TX buffer in order to not used the byte in
+                        * TXDR for the next transfer
+                        */
+                       mask = STM32F7_I2C_ISR_TXE;
+                       stm32f7_i2c_set_bits(base + STM32F7_I2C_ISR, mask);
+               }
+
+               /* Clear STOP flag */
+               writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR);
+
+               /* Notify i2c slave that a STOP flag has been detected */
+               i2c_slave_event(i2c_dev->slave_running, I2C_SLAVE_STOP, &val);
+
+               i2c_dev->slave_running = NULL;
+       }
+
+       /* Address match received */
+       if (status & STM32F7_I2C_ISR_ADDR)
+               stm32f7_i2c_slave_addr(i2c_dev);
+
+       return IRQ_HANDLED;
 }
 
 static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
@@ -673,6 +1371,13 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
        struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
        void __iomem *base = i2c_dev->base;
        u32 status, mask;
+       int ret = IRQ_HANDLED;
+
+       /* Check if the interrupt if for a slave device */
+       if (!i2c_dev->master_mode) {
+               ret = stm32f7_i2c_slave_isr_event(i2c_dev);
+               return ret;
+       }
 
        status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
 
@@ -694,12 +1399,21 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
        /* STOP detection flag */
        if (status & STM32F7_I2C_ISR_STOPF) {
                /* Disable interrupts */
-               stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_ALL_IRQ_MASK);
+               if (stm32f7_i2c_is_slave_registered(i2c_dev))
+                       mask = STM32F7_I2C_XFER_IRQ_MASK;
+               else
+                       mask = STM32F7_I2C_ALL_IRQ_MASK;
+               stm32f7_i2c_disable_irq(i2c_dev, mask);
 
                /* Clear STOP flag */
                writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR);
 
-               complete(&i2c_dev->complete);
+               if (i2c_dev->use_dma) {
+                       ret = IRQ_WAKE_THREAD;
+               } else {
+                       i2c_dev->master_mode = false;
+                       complete(&i2c_dev->complete);
+               }
        }
 
        /* Transfer complete */
@@ -707,6 +1421,10 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
                if (f7_msg->stop) {
                        mask = STM32F7_I2C_CR2_STOP;
                        stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
+               } else if (i2c_dev->use_dma) {
+                       ret = IRQ_WAKE_THREAD;
+               } else if (f7_msg->smbus) {
+                       stm32f7_i2c_smbus_rep_start(i2c_dev);
                } else {
                        i2c_dev->msg_id++;
                        i2c_dev->msg++;
@@ -714,13 +1432,50 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
                }
        }
 
+       if (status & STM32F7_I2C_ISR_TCR) {
+               if (f7_msg->smbus)
+                       stm32f7_i2c_smbus_reload(i2c_dev);
+               else
+                       stm32f7_i2c_reload(i2c_dev);
+       }
+
+       return ret;
+}
+
+static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data)
+{
+       struct stm32f7_i2c_dev *i2c_dev = data;
+       struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
+       struct stm32_i2c_dma *dma = i2c_dev->dma;
+       u32 status;
+       int ret;
+
        /*
-        * Transfer Complete Reload: 255 data bytes have been transferred
-        * We have to prepare the I2C controller to transfer the remaining
-        * data.
+        * Wait for dma transfer completion before sending next message or
+        * notity the end of xfer to the client
         */
-       if (status & STM32F7_I2C_ISR_TCR)
-               stm32f7_i2c_reload(i2c_dev);
+       ret = wait_for_completion_timeout(&i2c_dev->dma->dma_complete, HZ);
+       if (!ret) {
+               dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__);
+               stm32f7_i2c_disable_dma_req(i2c_dev);
+               dmaengine_terminate_all(dma->chan_using);
+               f7_msg->result = -ETIMEDOUT;
+       }
+
+       status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
+
+       if (status & STM32F7_I2C_ISR_TC) {
+               if (f7_msg->smbus) {
+                       stm32f7_i2c_smbus_rep_start(i2c_dev);
+               } else {
+                       i2c_dev->msg_id++;
+                       i2c_dev->msg++;
+                       stm32f7_i2c_xfer_msg(i2c_dev, i2c_dev->msg);
+               }
+       } else {
+               i2c_dev->master_mode = false;
+               complete(&i2c_dev->complete);
+       }
 
        return IRQ_HANDLED;
 }
@@ -731,7 +1486,8 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
        struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
        void __iomem *base = i2c_dev->base;
        struct device *dev = i2c_dev->dev;
-       u32 status;
+       struct stm32_i2c_dma *dma = i2c_dev->dma;
+       u32 mask, status;
 
        status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
 
@@ -739,6 +1495,7 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
        if (status & STM32F7_I2C_ISR_BERR) {
                dev_err(dev, "<%s>: Bus error\n", __func__);
                writel_relaxed(STM32F7_I2C_ICR_BERRCF, base + STM32F7_I2C_ICR);
+               stm32f7_i2c_release_bus(&i2c_dev->adap);
                f7_msg->result = -EIO;
        }
 
@@ -749,8 +1506,26 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
                f7_msg->result = -EAGAIN;
        }
 
-       stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_ALL_IRQ_MASK);
+       if (status & STM32F7_I2C_ISR_PECERR) {
+               dev_err(dev, "<%s>: PEC error in reception\n", __func__);
+               writel_relaxed(STM32F7_I2C_ICR_PECCF, base + STM32F7_I2C_ICR);
+               f7_msg->result = -EINVAL;
+       }
+
+       /* Disable interrupts */
+       if (stm32f7_i2c_is_slave_registered(i2c_dev))
+               mask = STM32F7_I2C_XFER_IRQ_MASK;
+       else
+               mask = STM32F7_I2C_ALL_IRQ_MASK;
+       stm32f7_i2c_disable_irq(i2c_dev, mask);
+
+       /* Disable dma */
+       if (i2c_dev->use_dma) {
+               stm32f7_i2c_disable_dma_req(i2c_dev);
+               dmaengine_terminate_all(dma->chan_using);
+       }
 
+       i2c_dev->master_mode = false;
        complete(&i2c_dev->complete);
 
        return IRQ_HANDLED;
@@ -761,12 +1536,14 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
 {
        struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
        struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
+       struct stm32_i2c_dma *dma = i2c_dev->dma;
        unsigned long time_left;
        int ret;
 
        i2c_dev->msg = msgs;
        i2c_dev->msg_num = num;
        i2c_dev->msg_id = 0;
+       f7_msg->smbus = false;
 
        ret = clk_enable(i2c_dev->clk);
        if (ret) {
@@ -787,6 +1564,8 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
        if (!time_left) {
                dev_dbg(i2c_dev->dev, "Access to slave 0x%x timed out\n",
                        i2c_dev->msg->addr);
+               if (i2c_dev->use_dma)
+                       dmaengine_terminate_all(dma->chan_using);
                ret = -ETIMEDOUT;
        }
 
@@ -796,14 +1575,209 @@ clk_free:
        return (ret < 0) ? ret : num;
 }
 
+static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
+                                 unsigned short flags, char read_write,
+                                 u8 command, int size,
+                                 union i2c_smbus_data *data)
+{
+       struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(adapter);
+       struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
+       struct stm32_i2c_dma *dma = i2c_dev->dma;
+       struct device *dev = i2c_dev->dev;
+       unsigned long timeout;
+       int i, ret;
+
+       f7_msg->addr = addr;
+       f7_msg->size = size;
+       f7_msg->read_write = read_write;
+       f7_msg->smbus = true;
+
+       ret = clk_enable(i2c_dev->clk);
+       if (ret) {
+               dev_err(i2c_dev->dev, "Failed to enable clock\n");
+               return ret;
+       }
+
+       ret = stm32f7_i2c_wait_free_bus(i2c_dev);
+       if (ret)
+               goto clk_free;
+
+       ret = stm32f7_i2c_smbus_xfer_msg(i2c_dev, flags, command, data);
+       if (ret)
+               goto clk_free;
+
+       timeout = wait_for_completion_timeout(&i2c_dev->complete,
+                                             i2c_dev->adap.timeout);
+       ret = f7_msg->result;
+       if (ret)
+               goto clk_free;
+
+       if (!timeout) {
+               dev_dbg(dev, "Access to slave 0x%x timed out\n", f7_msg->addr);
+               if (i2c_dev->use_dma)
+                       dmaengine_terminate_all(dma->chan_using);
+               ret = -ETIMEDOUT;
+               goto clk_free;
+       }
+
+       /* Check PEC */
+       if ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK && read_write) {
+               ret = stm32f7_i2c_smbus_check_pec(i2c_dev);
+               if (ret)
+                       goto clk_free;
+       }
+
+       if (read_write && size != I2C_SMBUS_QUICK) {
+               switch (size) {
+               case I2C_SMBUS_BYTE:
+               case I2C_SMBUS_BYTE_DATA:
+                       data->byte = f7_msg->smbus_buf[0];
+               break;
+               case I2C_SMBUS_WORD_DATA:
+               case I2C_SMBUS_PROC_CALL:
+                       data->word = f7_msg->smbus_buf[0] |
+                               (f7_msg->smbus_buf[1] << 8);
+               break;
+               case I2C_SMBUS_BLOCK_DATA:
+               case I2C_SMBUS_BLOCK_PROC_CALL:
+               for (i = 0; i <= f7_msg->smbus_buf[0]; i++)
+                       data->block[i] = f7_msg->smbus_buf[i];
+               break;
+               default:
+                       dev_err(dev, "Unsupported smbus transaction\n");
+                       ret = -EINVAL;
+               }
+       }
+
+clk_free:
+       clk_disable(i2c_dev->clk);
+       return ret;
+}
+
+static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
+{
+       struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(slave->adapter);
+       void __iomem *base = i2c_dev->base;
+       struct device *dev = i2c_dev->dev;
+       u32 oar1, oar2, mask;
+       int id, ret;
+
+       if (slave->flags & I2C_CLIENT_PEC) {
+               dev_err(dev, "SMBus PEC not supported in slave mode\n");
+               return -EINVAL;
+       }
+
+       if (stm32f7_i2c_is_slave_busy(i2c_dev)) {
+               dev_err(dev, "Too much slave registered\n");
+               return -EBUSY;
+       }
+
+       ret = stm32f7_i2c_get_free_slave_id(i2c_dev, slave, &id);
+       if (ret)
+               return ret;
+
+       if (!(stm32f7_i2c_is_slave_registered(i2c_dev))) {
+               ret = clk_enable(i2c_dev->clk);
+               if (ret) {
+                       dev_err(dev, "Failed to enable clock\n");
+                       return ret;
+               }
+       }
+
+       if (id == 0) {
+               /* Configure Own Address 1 */
+               oar1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR1);
+               oar1 &= ~STM32F7_I2C_OAR1_MASK;
+               if (slave->flags & I2C_CLIENT_TEN) {
+                       oar1 |= STM32F7_I2C_OAR1_OA1_10(slave->addr);
+                       oar1 |= STM32F7_I2C_OAR1_OA1MODE;
+               } else {
+                       oar1 |= STM32F7_I2C_OAR1_OA1_7(slave->addr);
+               }
+               oar1 |= STM32F7_I2C_OAR1_OA1EN;
+               i2c_dev->slave[id] = slave;
+               writel_relaxed(oar1, i2c_dev->base + STM32F7_I2C_OAR1);
+       } else if (id == 1) {
+               /* Configure Own Address 2 */
+               oar2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR2);
+               oar2 &= ~STM32F7_I2C_OAR2_MASK;
+               if (slave->flags & I2C_CLIENT_TEN) {
+                       ret = -EOPNOTSUPP;
+                       goto exit;
+               }
+
+               oar2 |= STM32F7_I2C_OAR2_OA2_7(slave->addr);
+               oar2 |= STM32F7_I2C_OAR2_OA2EN;
+               i2c_dev->slave[id] = slave;
+               writel_relaxed(oar2, i2c_dev->base + STM32F7_I2C_OAR2);
+       } else {
+               ret = -ENODEV;
+               goto exit;
+       }
+
+       /* Enable ACK */
+       stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR2, STM32F7_I2C_CR2_NACK);
+
+       /* Enable Address match interrupt, error interrupt and enable I2C  */
+       mask = STM32F7_I2C_CR1_ADDRIE | STM32F7_I2C_CR1_ERRIE |
+               STM32F7_I2C_CR1_PE;
+       stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
+
+       return 0;
+
+exit:
+       if (!(stm32f7_i2c_is_slave_registered(i2c_dev)))
+               clk_disable(i2c_dev->clk);
+
+       return ret;
+}
+
+static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)
+{
+       struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(slave->adapter);
+       void __iomem *base = i2c_dev->base;
+       u32 mask;
+       int id, ret;
+
+       ret = stm32f7_i2c_get_slave_id(i2c_dev, slave, &id);
+       if (ret)
+               return ret;
+
+       WARN_ON(!i2c_dev->slave[id]);
+
+       if (id == 0) {
+               mask = STM32F7_I2C_OAR1_OA1EN;
+               stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR1, mask);
+       } else {
+               mask = STM32F7_I2C_OAR2_OA2EN;
+               stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR2, mask);
+       }
+
+       i2c_dev->slave[id] = NULL;
+
+       if (!(stm32f7_i2c_is_slave_registered(i2c_dev))) {
+               stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_ALL_IRQ_MASK);
+               clk_disable(i2c_dev->clk);
+       }
+
+       return 0;
+}
+
 static u32 stm32f7_i2c_func(struct i2c_adapter *adap)
 {
-       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+       return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SLAVE |
+               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_BLOCK_PROC_CALL |
+               I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PEC;
 }
 
 static struct i2c_algorithm stm32f7_i2c_algo = {
        .master_xfer = stm32f7_i2c_xfer,
+       .smbus_xfer = stm32f7_i2c_smbus_xfer,
        .functionality = stm32f7_i2c_func,
+       .reg_slave = stm32f7_i2c_reg_slave,
+       .unreg_slave = stm32f7_i2c_unreg_slave,
 };
 
 static int stm32f7_i2c_probe(struct platform_device *pdev)
@@ -815,6 +1789,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
        u32 irq_error, irq_event, clk_rate, rise_time, fall_time;
        struct i2c_adapter *adap;
        struct reset_control *rst;
+       dma_addr_t phy_addr;
        int ret;
 
        i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
@@ -825,6 +1800,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
        i2c_dev->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(i2c_dev->base))
                return PTR_ERR(i2c_dev->base);
+       phy_addr = (dma_addr_t)res->start;
 
        irq_event = irq_of_parse_and_map(np, 0);
        if (!irq_event) {
@@ -871,8 +1847,11 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
 
        i2c_dev->dev = &pdev->dev;
 
-       ret = devm_request_irq(&pdev->dev, irq_event, stm32f7_i2c_isr_event, 0,
-                              pdev->name, i2c_dev);
+       ret = devm_request_threaded_irq(&pdev->dev, irq_event,
+                                       stm32f7_i2c_isr_event,
+                                       stm32f7_i2c_isr_event_thread,
+                                       IRQF_ONESHOT,
+                                       pdev->name, i2c_dev);
        if (ret) {
                dev_err(&pdev->dev, "Failed to request irq event %i\n",
                        irq_event);
@@ -924,6 +1903,11 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
 
        init_completion(&i2c_dev->complete);
 
+       /* Init DMA config if supported */
+       i2c_dev->dma = stm32_i2c_dma_request(i2c_dev->dev, phy_addr,
+                                            STM32F7_I2C_TXDR,
+                                            STM32F7_I2C_RXDR);
+
        ret = i2c_add_adapter(adap);
        if (ret)
                goto clk_free;
@@ -946,6 +1930,11 @@ static int stm32f7_i2c_remove(struct platform_device *pdev)
 {
        struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
 
+       if (i2c_dev->dma) {
+               stm32_i2c_dma_free(i2c_dev->dma);
+               i2c_dev->dma = NULL;
+       }
+
        i2c_del_adapter(&i2c_dev->adap);
 
        clk_unprepare(i2c_dev->clk);
index dc63236..e866c48 100644 (file)
@@ -602,20 +602,24 @@ static int stu300_send_address(struct stu300_dev *dev,
        u32 val;
        int ret;
 
-       if (msg->flags & I2C_M_TEN)
+       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;
-       else
-               val = ((msg->addr << 1) & 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 (msg->flags & I2C_M_RD) {
-               /* This is the direction bit */
-               val |= 0x01;
-               if (resend)
+       if (resend) {
+               if (msg->flags & I2C_M_RD)
                        dev_dbg(&dev->pdev->dev, "read resend\n");
-       } else if (resend)
-               dev_dbg(&dev->pdev->dev, "write 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) */
index a021f86..915f5ed 100644 (file)
@@ -509,7 +509,7 @@ static int synquacer_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
 
        dev_dbg(i2c->dev, "calculated timeout %d ms\n", i2c->timeout_ms);
 
-       for (retry = 0; retry < adap->retries; retry++) {
+       for (retry = 0; retry <= adap->retries; retry++) {
                ret = synquacer_i2c_doxfer(i2c, msgs, num);
                if (ret != -EAGAIN)
                        return ret;
index 60292d2..5fccd1f 100644 (file)
@@ -173,7 +173,6 @@ struct tegra_i2c_hw_feature {
  * @msg_buf_remaining: size of unsent data in the message buffer
  * @msg_read: identifies read transfers
  * @bus_clk_rate: current i2c bus clock rate
- * @is_suspended: prevents i2c controller accesses after suspend is called
  */
 struct tegra_i2c_dev {
        struct device *dev;
@@ -194,7 +193,6 @@ struct tegra_i2c_dev {
        int msg_read;
        u32 bus_clk_rate;
        u16 clk_divisor_non_hs_mode;
-       bool is_suspended;
        bool is_multimaster_mode;
        spinlock_t xfer_lock;
 };
@@ -734,9 +732,6 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
        int i;
        int ret = 0;
 
-       if (i2c_dev->is_suspended)
-               return -EBUSY;
-
        ret = pm_runtime_get_sync(i2c_dev->dev);
        if (ret < 0) {
                dev_err(i2c_dev->dev, "runtime resume failed %d\n", ret);
@@ -1051,37 +1046,9 @@ static int tegra_i2c_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM_SLEEP
-static int tegra_i2c_suspend(struct device *dev)
-{
-       struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
-
-       i2c_lock_adapter(&i2c_dev->adapter);
-       i2c_dev->is_suspended = true;
-       i2c_unlock_adapter(&i2c_dev->adapter);
-
-       return 0;
-}
-
-static int tegra_i2c_resume(struct device *dev)
-{
-       struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
-       int ret;
-
-       i2c_lock_adapter(&i2c_dev->adapter);
-
-       ret = tegra_i2c_init(i2c_dev);
-       if (!ret)
-               i2c_dev->is_suspended = false;
-
-       i2c_unlock_adapter(&i2c_dev->adapter);
-
-       return ret;
-}
-
 static const struct dev_pm_ops tegra_i2c_pm = {
        SET_RUNTIME_PM_OPS(tegra_i2c_runtime_suspend, tegra_i2c_runtime_resume,
                           NULL)
-       SET_SYSTEM_SLEEP_PM_OPS(tegra_i2c_suspend, tegra_i2c_resume)
 };
 #define TEGRA_I2C_PM   (&tegra_i2c_pm)
 #else
index c805278..9a71e50 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/wait.h>
-#include <linux/i2c-xiic.h>
+#include <linux/platform_data/i2c-xiic.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/of.h>
@@ -143,12 +143,6 @@ struct xiic_i2c {
 
 #define XIIC_TX_RX_INTERRUPTS (XIIC_INTR_RX_FULL_MASK | XIIC_TX_INTERRUPTS)
 
-/* The following constants are used with the following macros to specify the
- * operation, a read or write operation.
- */
-#define XIIC_READ_OPERATION  1
-#define XIIC_WRITE_OPERATION 0
-
 /*
  * Tx Fifo upper bit masks.
  */
@@ -415,7 +409,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
                clr |= XIIC_INTR_RX_FULL_MASK;
                if (!i2c->rx_msg) {
                        dev_dbg(i2c->adap.dev.parent,
-                               "%s unexpexted RX IRQ\n", __func__);
+                               "%s unexpected RX IRQ\n", __func__);
                        xiic_clear_rx_fifo(i2c);
                        goto out;
                }
@@ -470,7 +464,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
 
                if (!i2c->tx_msg) {
                        dev_dbg(i2c->adap.dev.parent,
-                               "%s unexpexted TX IRQ\n", __func__);
+                               "%s unexpected TX IRQ\n", __func__);
                        goto out;
                }
 
@@ -556,8 +550,7 @@ static void xiic_start_recv(struct xiic_i2c *i2c)
        if (!(msg->flags & I2C_M_NOSTART))
                /* write the address */
                xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET,
-                       (msg->addr << 1) | XIIC_READ_OPERATION |
-                       XIIC_TX_DYN_START_MASK);
+                       i2c_8bit_addr_from_msg(msg) | XIIC_TX_DYN_START_MASK);
 
        xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK);
 
@@ -585,7 +578,7 @@ static void xiic_start_send(struct xiic_i2c *i2c)
 
        if (!(msg->flags & I2C_M_NOSTART)) {
                /* write the address */
-               u16 data = ((msg->addr << 1) & 0xfe) | XIIC_WRITE_OPERATION |
+               u16 data = i2c_8bit_addr_from_msg(msg) |
                        XIIC_TX_DYN_START_MASK;
                if ((i2c->nmsgs == 1) && msg->len == 0)
                        /* no data and last message -> add STOP */
index eb8913e..1f41a4f 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/clk.h>
 #include <linux/completion.h>
 #include <linux/i2c.h>
+#include <linux/i2c-smbus.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -84,6 +85,8 @@ struct xlp9xx_i2c_dev {
        struct device *dev;
        struct i2c_adapter adapter;
        struct completion msg_complete;
+       struct i2c_smbus_alert_setup alert_data;
+       struct i2c_client *ara;
        int irq;
        bool msg_read;
        bool len_recv;
@@ -155,9 +158,30 @@ static void xlp9xx_i2c_fill_tx_fifo(struct xlp9xx_i2c_dev *priv)
        priv->msg_buf += len;
 }
 
+static void xlp9xx_i2c_update_rlen(struct xlp9xx_i2c_dev *priv)
+{
+       u32 val, len;
+
+       /*
+        * Update receive length. Re-read len to get the latest value,
+        * and then add 4 to have a minimum value that can be safely
+        * written. This is to account for the byte read above, the
+        * transfer in progress and any delays in the register I/O
+        */
+       val = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_CTRL);
+       len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) &
+                                 XLP9XX_I2C_FIFO_WCNT_MASK;
+       len = max_t(u32, priv->msg_len, len + 4);
+       if (len >= I2C_SMBUS_BLOCK_MAX + 2)
+               return;
+       val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) |
+                       (len << XLP9XX_I2C_CTRL_MCTLEN_SHIFT);
+       xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, val);
+}
+
 static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)
 {
-       u32 len, i, val;
+       u32 len, i;
        u8 rlen, *buf = priv->msg_buf;
 
        len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) &
@@ -167,21 +191,20 @@ static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)
        if (priv->len_recv) {
                /* read length byte */
                rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
-               *buf++ = rlen;
-               len--;
-
-               if (priv->client_pec)
-                       ++rlen;
-               /* update remaining bytes and message length */
-               priv->msg_buf_remaining = rlen;
-               priv->msg_len = rlen + 1;
+               if (rlen > I2C_SMBUS_BLOCK_MAX || rlen == 0) {
+                       rlen = 0;       /*abort transfer */
+                       priv->msg_buf_remaining = 0;
+                       priv->msg_len = 0;
+               } else {
+                       *buf++ = rlen;
+                       if (priv->client_pec)
+                               ++rlen; /* account for error check byte */
+                       /* update remaining bytes and message length */
+                       priv->msg_buf_remaining = rlen;
+                       priv->msg_len = rlen + 1;
+               }
+               xlp9xx_i2c_update_rlen(priv);
                priv->len_recv = false;
-
-               /* Update transfer length to read only actual data */
-               val = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_CTRL);
-               val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) |
-                       ((rlen + 1) << XLP9XX_I2C_CTRL_MCTLEN_SHIFT);
-               xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, val);
        } else {
                len = min(priv->msg_buf_remaining, len);
                for (i = 0; i < len; i++, buf++)
@@ -300,10 +323,6 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
        xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_MFIFOCTRL,
                             XLP9XX_I2C_MFIFOCTRL_RST);
 
-       /* set FIFO threshold if reading */
-       if (priv->msg_read)
-               xlp9xx_i2c_update_rx_fifo_thres(priv);
-
        /* set slave addr */
        xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_SLAVEADDR,
                             (msg->addr << XLP9XX_I2C_SLAVEADDR_ADDR_SHIFT) |
@@ -322,9 +341,13 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
                val &= ~XLP9XX_I2C_CTRL_ADDMODE;
 
        priv->len_recv = msg->flags & I2C_M_RECV_LEN;
-       len = priv->len_recv ? XLP9XX_I2C_FIFO_SIZE : msg->len;
+       len = priv->len_recv ? I2C_SMBUS_BLOCK_MAX + 2 : msg->len;
        priv->client_pec = msg->flags & I2C_CLIENT_PEC;
 
+       /* set FIFO threshold if reading */
+       if (priv->msg_read)
+               xlp9xx_i2c_update_rx_fifo_thres(priv);
+
        /* set data length to be transferred */
        val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) |
              (len << XLP9XX_I2C_CTRL_MCTLEN_SHIFT);
@@ -378,8 +401,11 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
        }
 
        /* update msg->len with actual received length */
-       if (msg->flags & I2C_M_RECV_LEN)
+       if (msg->flags & I2C_M_RECV_LEN) {
+               if (!priv->msg_len)
+                       return -EPROTO;
                msg->len = priv->msg_len;
+       }
        return 0;
 }
 
@@ -447,6 +473,19 @@ static int xlp9xx_i2c_get_frequency(struct platform_device *pdev,
        return 0;
 }
 
+static int xlp9xx_i2c_smbus_setup(struct xlp9xx_i2c_dev *priv,
+                                 struct platform_device *pdev)
+{
+       if (!priv->alert_data.irq)
+               return -EINVAL;
+
+       priv->ara = i2c_setup_smbus_alert(&priv->adapter, &priv->alert_data);
+       if (!priv->ara)
+               return -ENODEV;
+
+       return 0;
+}
+
 static int xlp9xx_i2c_probe(struct platform_device *pdev)
 {
        struct xlp9xx_i2c_dev *priv;
@@ -467,6 +506,10 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "invalid irq!\n");
                return priv->irq;
        }
+       /* SMBAlert irq */
+       priv->alert_data.irq = platform_get_irq(pdev, 1);
+       if (priv->alert_data.irq <= 0)
+               priv->alert_data.irq = 0;
 
        xlp9xx_i2c_get_frequency(pdev, priv);
        xlp9xx_i2c_init(priv);
@@ -493,6 +536,10 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev)
        if (err)
                return err;
 
+       err = xlp9xx_i2c_smbus_setup(priv, pdev);
+       if (err)
+               dev_dbg(&pdev->dev, "No active SMBus alert %d\n", err);
+
        platform_set_drvdata(pdev, priv);
        dev_dbg(&pdev->dev, "I2C bus:%d added\n", priv->adapter.nr);
 
index a17f46a..31d16ad 100644 (file)
@@ -717,10 +717,6 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
        client->adapter = adap;
 
        client->dev.platform_data = info->platform_data;
-
-       if (info->archdata)
-               client->dev.archdata = *info->archdata;
-
        client->flags = info->flags;
        client->addr = info->addr;
 
@@ -746,7 +742,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
        client->dev.parent = &client->adapter->dev;
        client->dev.bus = &i2c_bus_type;
        client->dev.type = &i2c_client_type;
-       client->dev.of_node = info->of_node;
+       client->dev.of_node = of_node_get(info->of_node);
        client->dev.fwnode = info->fwnode;
 
        i2c_dev_set_name(adap, client, info);
@@ -757,7 +753,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
                        dev_err(&adap->dev,
                                "Failed to add properties to client %s: %d\n",
                                client->name, status);
-                       goto out_err;
+                       goto out_err_put_of_node;
                }
        }
 
@@ -773,6 +769,8 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
 out_free_props:
        if (info->properties)
                device_remove_properties(&client->dev);
+out_err_put_of_node:
+       of_node_put(info->of_node);
 out_err:
        dev_err(&adap->dev,
                "Failed to register i2c client %s at 0x%02x (%d)\n",
index c405270..6cb7ad6 100644 (file)
 
 #include "i2c-core.h"
 
-static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
-                                                struct device_node *node)
+int of_i2c_get_board_info(struct device *dev, struct device_node *node,
+                         struct i2c_board_info *info)
 {
-       struct i2c_client *client;
-       struct i2c_board_info info = {};
-       struct dev_archdata dev_ad = {};
        u32 addr;
        int ret;
 
-       dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node);
+       memset(info, 0, sizeof(*info));
 
-       if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
-               dev_err(&adap->dev, "of_i2c: modalias failure on %pOF\n",
-                       node);
-               return ERR_PTR(-EINVAL);
+       if (of_modalias_node(node, info->type, sizeof(info->type)) < 0) {
+               dev_err(dev, "of_i2c: modalias failure on %pOF\n", node);
+               return -EINVAL;
        }
 
        ret = of_property_read_u32(node, "reg", &addr);
        if (ret) {
-               dev_err(&adap->dev, "of_i2c: invalid reg on %pOF\n", node);
-               return ERR_PTR(ret);
+               dev_err(dev, "of_i2c: invalid reg on %pOF\n", node);
+               return ret;
        }
 
        if (addr & I2C_TEN_BIT_ADDRESS) {
                addr &= ~I2C_TEN_BIT_ADDRESS;
-               info.flags |= I2C_CLIENT_TEN;
+               info->flags |= I2C_CLIENT_TEN;
        }
 
        if (addr & I2C_OWN_SLAVE_ADDRESS) {
                addr &= ~I2C_OWN_SLAVE_ADDRESS;
-               info.flags |= I2C_CLIENT_SLAVE;
+               info->flags |= I2C_CLIENT_SLAVE;
        }
 
-       info.addr = addr;
-       info.archdata = &dev_ad;
-       info.of_node = of_node_get(node);
+       info->addr = addr;
+       info->of_node = node;
 
        if (of_property_read_bool(node, "host-notify"))
-               info.flags |= I2C_CLIENT_HOST_NOTIFY;
+               info->flags |= I2C_CLIENT_HOST_NOTIFY;
 
        if (of_get_property(node, "wakeup-source", NULL))
-               info.flags |= I2C_CLIENT_WAKE;
+               info->flags |= I2C_CLIENT_WAKE;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_i2c_get_board_info);
+
+static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
+                                                struct device_node *node)
+{
+       struct i2c_client *client;
+       struct i2c_board_info info;
+       int ret;
+
+       dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node);
+
+       ret = of_i2c_get_board_info(&adap->dev, node, &info);
+       if (ret)
+               return ERR_PTR(ret);
 
        client = i2c_new_device(adap, &info);
        if (!client) {
                dev_err(&adap->dev, "of_i2c: Failure registering %pOF\n", node);
-               of_node_put(node);
                return ERR_PTR(-EINVAL);
        }
        return client;
index b5aec33..f3f6830 100644 (file)
@@ -466,6 +466,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
        status = i2c_transfer(adapter, msg, num);
        if (status < 0)
                return status;
+       if (status != num)
+               return -EIO;
 
        /* Check PEC if last message is a read */
        if (i && (msg[num-1].flags & I2C_M_RD)) {
index 9669ca4..300ab4b 100644 (file)
@@ -418,7 +418,7 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
        snprintf(symlink_name, sizeof(symlink_name), "channel-%u", chan_id);
        WARN(sysfs_create_link(&muxc->dev->kobj, &priv->adap.dev.kobj,
                               symlink_name),
-            "can't create symlink for channel %u\n", chan_id);
+            "can't create symlink to channel %u\n", chan_id);
        dev_info(&parent->dev, "Added multiplexed i2c bus %d\n",
                 i2c_adapter_id(&priv->adap));
 
index 33ce032..035032e 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/of.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/sysfs.h>
 
@@ -105,7 +106,7 @@ static int i2c_demux_activate_master(struct i2c_demux_pinctrl_priv *priv, u32 ne
        priv->cur_adap.owner = THIS_MODULE;
        priv->cur_adap.algo = &priv->algo;
        priv->cur_adap.algo_data = priv;
-       priv->cur_adap.dev.parent = priv->dev;
+       priv->cur_adap.dev.parent = &adap->dev;
        priv->cur_adap.class = adap->class;
        priv->cur_adap.retries = adap->retries;
        priv->cur_adap.timeout = adap->timeout;
@@ -254,6 +255,8 @@ static int i2c_demux_pinctrl_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, priv);
 
+       pm_runtime_no_callbacks(&pdev->dev);
+
        /* switch to first parent as active master */
        i2c_demux_activate_master(priv, 0);
 
index ddc4bd4..401308e 100644 (file)
@@ -10,7 +10,7 @@
 
 #include <linux/i2c.h>
 #include <linux/i2c-mux.h>
-#include <linux/i2c-mux-gpio.h>
+#include <linux/platform_data/i2c-mux-gpio.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include <linux/slab.h>
index 311b1cc..a9af932 100644 (file)
@@ -206,8 +206,7 @@ static const struct of_device_id ltc4306_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, ltc4306_of_match);
 
-static int ltc4306_probe(struct i2c_client *client,
-                        const struct i2c_device_id *id)
+static int ltc4306_probe(struct i2c_client *client)
 {
        struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
        const struct chip_desc *chip;
@@ -221,7 +220,7 @@ static int ltc4306_probe(struct i2c_client *client,
        chip = of_device_get_match_data(&client->dev);
 
        if (!chip)
-               chip = &chips[id->driver_data];
+               chip = &chips[i2c_match_id(ltc4306_id, client)->driver_data];
 
        idle_disc = device_property_read_bool(&client->dev,
                                              "i2c-mux-idle-disconnect");
@@ -310,7 +309,7 @@ static struct i2c_driver ltc4306_driver = {
                .name   = "ltc4306",
                .of_match_table = of_match_ptr(ltc4306_of_match),
        },
-       .probe          = ltc4306_probe,
+       .probe_new      = ltc4306_probe,
        .remove         = ltc4306_remove,
        .id_table       = ltc4306_id,
 };
index 09bafd3..fbc7480 100644 (file)
@@ -36,6 +36,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/delay.h>
 #include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/i2c-mux.h>
@@ -373,7 +374,6 @@ static int pca954x_probe(struct i2c_client *client,
        int num, force, class;
        struct i2c_mux_core *muxc;
        struct pca954x *data;
-       const struct of_device_id *match;
        int ret;
 
        if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
@@ -389,15 +389,19 @@ static int pca954x_probe(struct i2c_client *client,
        i2c_set_clientdata(client, muxc);
        data->client = client;
 
-       /* Get the mux out of reset if a reset GPIO is specified. */
-       gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW);
+       /* Reset the mux if a reset GPIO is specified. */
+       gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH);
        if (IS_ERR(gpio))
                return PTR_ERR(gpio);
+       if (gpio) {
+               udelay(1);
+               gpiod_set_value_cansleep(gpio, 0);
+               /* Give the chip some time to recover. */
+               udelay(1);
+       }
 
-       match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev);
-       if (match)
-               data->chip = of_device_get_match_data(&client->dev);
-       else
+       data->chip = of_device_get_match_data(&client->dev);
+       if (!data->chip)
                data->chip = &chips[id->driver_data];
 
        if (data->chip->id.manufacturer_id != I2C_DEVICE_ID_NONE) {
index f583f80..5653295 100644 (file)
@@ -127,10 +127,8 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
        values = devm_kcalloc(&pdev->dev,
                              mux->data.n_values, sizeof(*mux->data.values),
                              GFP_KERNEL);
-       if (!values) {
-               dev_err(&pdev->dev, "Cannot allocate values array");
+       if (!values)
                return -ENOMEM;
-       }
 
        for_each_child_of_node(np, child) {
                of_property_read_u32(child, "reg", values + i);
index 3cf3000..6d9f0ab 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
index 55d19fd..2a87b0d 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/pci.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
 #include <linux/gpio/machine.h>
 #include <linux/slab.h>
 
index 05ecf82..436e347 100644 (file)
@@ -30,8 +30,8 @@
 #include <linux/timb_gpio.h>
 
 #include <linux/i2c.h>
-#include <linux/i2c-ocores.h>
-#include <linux/i2c-xiic.h>
+#include <linux/platform_data/i2c-ocores.h>
+#include <linux/platform_data/i2c-xiic.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/xilinx_spi.h>
index 33053b0..f5cc517 100644 (file)
@@ -532,6 +532,45 @@ static int at24_get_pdata(struct device *dev, struct at24_platform_data *pdata)
        return 0;
 }
 
+static void at24_remove_dummy_clients(struct at24_data *at24)
+{
+       int i;
+
+       for (i = 1; i < at24->num_addresses; i++)
+               i2c_unregister_device(at24->client[i].client);
+}
+
+static int at24_make_dummy_client(struct at24_data *at24, unsigned int index,
+                                 struct regmap_config *regmap_config)
+{
+       struct i2c_client *base_client, *dummy_client;
+       unsigned short int addr;
+       struct regmap *regmap;
+       struct device *dev;
+
+       base_client = at24->client[0].client;
+       dev = &base_client->dev;
+       addr = base_client->addr + index;
+
+       dummy_client = i2c_new_dummy(base_client->adapter,
+                                    base_client->addr + index);
+       if (!dummy_client) {
+               dev_err(dev, "address 0x%02x unavailable\n", addr);
+               return -EADDRINUSE;
+       }
+
+       regmap = devm_regmap_init_i2c(dummy_client, regmap_config);
+       if (IS_ERR(regmap)) {
+               i2c_unregister_device(dummy_client);
+               return PTR_ERR(regmap);
+       }
+
+       at24->client[index].client = dummy_client;
+       at24->client[index].regmap = regmap;
+
+       return 0;
+}
+
 static unsigned int at24_get_offset_adj(u8 flags, unsigned int byte_len)
 {
        if (flags & AT24_FLAG_MAC) {
@@ -637,20 +676,10 @@ static int at24_probe(struct i2c_client *client)
 
        /* use dummy devices for multiple-address chips */
        for (i = 1; i < num_addresses; i++) {
-               at24->client[i].client = i2c_new_dummy(client->adapter,
-                                                      client->addr + i);
-               if (!at24->client[i].client) {
-                       dev_err(dev, "address 0x%02x unavailable\n",
-                               client->addr + i);
-                       err = -EADDRINUSE;
-                       goto err_clients;
-               }
-               at24->client[i].regmap = devm_regmap_init_i2c(
-                                               at24->client[i].client,
-                                               &regmap_config);
-               if (IS_ERR(at24->client[i].regmap)) {
-                       err = PTR_ERR(at24->client[i].regmap);
-                       goto err_clients;
+               err = at24_make_dummy_client(at24, i, &regmap_config);
+               if (err) {
+                       at24_remove_dummy_clients(at24);
+                       return err;
                }
        }
 
@@ -685,7 +714,7 @@ static int at24_probe(struct i2c_client *client)
        nvmem_config.word_size = 1;
        nvmem_config.size = pdata.byte_len;
 
-       at24->nvmem = nvmem_register(&nvmem_config);
+       at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
        if (IS_ERR(at24->nvmem)) {
                err = PTR_ERR(at24->nvmem);
                goto err_clients;
@@ -702,10 +731,7 @@ static int at24_probe(struct i2c_client *client)
        return 0;
 
 err_clients:
-       for (i = 1; i < num_addresses; i++)
-               if (at24->client[i].client)
-                       i2c_unregister_device(at24->client[i].client);
-
+       at24_remove_dummy_clients(at24);
        pm_runtime_disable(dev);
 
        return err;
@@ -714,15 +740,10 @@ err_clients:
 static int at24_remove(struct i2c_client *client)
 {
        struct at24_data *at24;
-       int i;
 
        at24 = i2c_get_clientdata(client);
 
-       nvmem_unregister(at24->nvmem);
-
-       for (i = 1; i < at24->num_addresses; i++)
-               i2c_unregister_device(at24->client[i].client);
-
+       at24_remove_dummy_clients(at24);
        pm_runtime_disable(&client->dev);
        pm_runtime_set_suspended(&client->dev);
 
diff --git a/include/linux/i2c-pnx.h b/include/linux/i2c-pnx.h
deleted file mode 100644 (file)
index 5388326..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Header file for I2C support on PNX010x/4008.
- *
- * Author: Dennis Kovalev <dkovalev@ru.mvista.com>
- *
- * 2004-2006 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef __I2C_PNX_H__
-#define __I2C_PNX_H__
-
-struct platform_device;
-struct clk;
-
-struct i2c_pnx_mif {
-       int                     ret;            /* Return value */
-       int                     mode;           /* Interface mode */
-       struct completion       complete;       /* I/O completion */
-       struct timer_list       timer;          /* Timeout */
-       u8 *                    buf;            /* Data buffer */
-       int                     len;            /* Length of data buffer */
-       int                     order;          /* RX Bytes to order via TX */
-};
-
-struct i2c_pnx_algo_data {
-       void __iomem            *ioaddr;
-       struct i2c_pnx_mif      mif;
-       int                     last;
-       struct clk              *clk;
-       struct i2c_adapter      adapter;
-       int                     irq;
-       u32                     timeout;
-};
-
-#endif /* __I2C_PNX_H__ */
index 44ad14e..254cd34 100644 (file)
@@ -394,7 +394,6 @@ static inline bool i2c_detect_slave_mode(struct device *dev) { return false; }
  * @addr: stored in i2c_client.addr
  * @dev_name: Overrides the default <busnr>-<addr> dev_name if set
  * @platform_data: stored in i2c_client.dev.platform_data
- * @archdata: copied into i2c_client.dev.archdata
  * @of_node: pointer to OpenFirmware device node
  * @fwnode: device node supplied by the platform firmware
  * @properties: additional device properties for the device
@@ -419,7 +418,6 @@ struct i2c_board_info {
        unsigned short  addr;
        const char      *dev_name;
        void            *platform_data;
-       struct dev_archdata     *archdata;
        struct device_node *of_node;
        struct fwnode_handle *fwnode;
        const struct property_entry *properties;
@@ -903,6 +901,9 @@ extern const struct of_device_id
 *i2c_of_match_device(const struct of_device_id *matches,
                     struct i2c_client *client);
 
+int of_i2c_get_board_info(struct device *dev, struct device_node *node,
+                         struct i2c_board_info *info);
+
 #else
 
 static inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
@@ -927,6 +928,13 @@ static inline const struct of_device_id
        return NULL;
 }
 
+static inline int of_i2c_get_board_info(struct device *dev,
+                                       struct device_node *node,
+                                       struct i2c_board_info *info)
+{
+       return -ENOTSUPP;
+}
+
 #endif /* CONFIG_OF */
 
 #if IS_ENABLED(CONFIG_ACPI)