Merge branch 'i2c/for-5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 22 Feb 2021 17:02:24 +0000 (09:02 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 22 Feb 2021 17:02:24 +0000 (09:02 -0800)
Pull i2c updates from Wolfram Sang:

 - mostly driver updates. Bigger ones for mlxcpld and iproc. But most of
   them are all over the place.

 - removal of the efm32, sirf, u300, and zte zx bus drivers because of
   platform removal. So, we have a pleasant diffstat this time.

 - first set of cleanups in the I2C core as preparation to increase
   maximum length of SMBus transfers to 255 (as specified in the new
   standard). Better documentation of struct i2c_msg and its flags stand
   out here.

 - the testunit can now respond to SMBus block process calls which is
   the testcase when implementing the above new maximum length.

* 'i2c/for-5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (62 commits)
  i2c: remove redundant error print in stm32f7_i2c_probe
  i2c: testunit: add support for block process calls
  i2c: busses: Replace spin_lock_irqsave with spin_lock in hard IRQ
  dt-bindings: eeprom: at24: Document ROHM BR24G01
  i2c: i801: Add support for Intel Alder Lake PCH-P
  i2c: mv64xxx: Fix check for missing clock after adding RPM
  i2c: mux: mlxcpld: Add callback to notify mux creation completion
  i2c: mux: mlxcpld: Extend supported mux number
  i2c: mux: mlxcpld: Extend driver to support word address space devices
  i2c: mux: mlxcpld: Get rid of adapter numbers enforcement
  i2c: mux: mlxcpld: Prepare mux selection infrastructure for two-byte support
  i2c: mux: mlxcpld: Convert driver to platform driver
  i2c: imx: Synthesize end of transaction events without idle interrupts
  i2c: i2c-qcom-geni: Add shutdown callback for i2c
  i2c: mv64xxx: Add runtime PM support
  i2c: amd-mp2: Remove unused macro
  i2c: amd-mp2: convert to PCI logging functions
  i2c: mux: mlxcpld: Move header file out of x86 realm
  platform/x86: mlxcpld: Update module license
  i2c: mux: mlxcpld: Update module license
  ...

44 files changed:
Documentation/devicetree/bindings/eeprom/at24.yaml
Documentation/devicetree/bindings/i2c/i2c-sirf.txt [deleted file]
Documentation/devicetree/bindings/i2c/i2c-stu300.txt [deleted file]
Documentation/devicetree/bindings/i2c/i2c-zx2967.txt [deleted file]
Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
Documentation/devicetree/bindings/i2c/renesas,i2c.txt
Documentation/i2c/slave-testunit-backend.rst
drivers/gpio/gpiolib.c
drivers/i2c/algos/i2c-algo-bit.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-amd-mp2-pci.c
drivers/i2c/busses/i2c-amd-mp2-plat.c
drivers/i2c/busses/i2c-amd-mp2.h
drivers/i2c/busses/i2c-bcm-iproc.c
drivers/i2c/busses/i2c-digicolor.c
drivers/i2c/busses/i2c-efm32.c [deleted file]
drivers/i2c/busses/i2c-elektor.c
drivers/i2c/busses/i2c-gpio.c
drivers/i2c/busses/i2c-hix5hd2.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-jz4780.c
drivers/i2c/busses/i2c-mlxcpld.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-qcom-geni.c
drivers/i2c/busses/i2c-qup.c
drivers/i2c/busses/i2c-rcar.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-sirf.c [deleted file]
drivers/i2c/busses/i2c-stm32f7.c
drivers/i2c/busses/i2c-stu300.c [deleted file]
drivers/i2c/busses/i2c-tegra.c
drivers/i2c/busses/i2c-zx2967.c [deleted file]
drivers/i2c/i2c-core-acpi.c
drivers/i2c/i2c-core-smbus.c
drivers/i2c/i2c-slave-testunit.c
drivers/i2c/i2c-stub.c
drivers/i2c/muxes/i2c-mux-gpio.c
drivers/i2c/muxes/i2c-mux-mlxcpld.c
include/linux/platform_data/mlxcpld.h [new file with mode: 0644]
include/linux/platform_data/x86/mlxcpld.h [deleted file]
include/uapi/linux/i2c-dev.h
include/uapi/linux/i2c.h

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