Merge tag 'i2c-for-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 25 Feb 2023 01:12:23 +0000 (17:12 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 25 Feb 2023 01:12:23 +0000 (17:12 -0800)
Pull i2c updates from Wolfram Sang:

 - new drivers for HPE GXP and Loongson 2K/LS7A

 - bigger refactorings for i801 and xiic

 - gpio driver gained ACPI and SDA-write only support

 - the core converted some OF helpers to fwnode helpers

 - usual bunch of driver updates

* tag 'i2c-for-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (52 commits)
  MAINTAINERS: Add HPE GXP I2C Support
  i2c: Add GXP SoC I2C Controller
  dt-bindings: i2c: Add hpe,gxp-i2c
  i2c: xiic: Remove some dead code
  i2c: xiic: Add SCL frequency configuration support
  i2c: xiic: Update compatible with new IP version
  dt-bindings: i2c: xiic: Add 'xlnx,axi-iic-2.1' to compatible
  i2c: i801: Call i801_check_post() from i801_access()
  i2c: i801: Call i801_check_pre() from i801_access()
  i2c: i801: Centralize configuring block commands in i801_block_transaction
  i2c: i801: Centralize configuring non-block commands in i801_simple_transaction
  i2c: i801: Handle SMBAUXCTL_E32B in i801_block_transaction_by_block only
  i2c: i801: Add i801_simple_transaction(), complementing i801_block_transaction()
  Documentation: i2c: correct spelling
  dt-bindings: i2c: i2c-st: convert to DT schema
  i2c: i801: add helper i801_set_hstadd()
  i2c: i801: make FEATURE_BLOCK_PROC dependent on FEATURE_BLOCK_BUFFER
  i2c: i801: make FEATURE_HOST_NOTIFY dependent on FEATURE_IRQ
  i2c: i801: improve interrupt handler
  i2c: st: use pm_sleep_ptr to avoid ifdef CONFIG_PM_SLEEP
  ...

37 files changed:
Documentation/devicetree/bindings/i2c/hpe,gxp-i2c.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/i2c-gpio.yaml
Documentation/devicetree/bindings/i2c/i2c-mt65xx.yaml
Documentation/devicetree/bindings/i2c/i2c-st.txt [deleted file]
Documentation/devicetree/bindings/i2c/loongson,ls2x-i2c.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/qcom,i2c-cci.yaml
Documentation/devicetree/bindings/i2c/socionext,uniphier-fi2c.yaml
Documentation/devicetree/bindings/i2c/socionext,uniphier-i2c.yaml
Documentation/devicetree/bindings/i2c/st,sti-i2c.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/xlnx,xps-iic-2.00.a.yaml
Documentation/i2c/gpio-fault-injection.rst
Documentation/i2c/smbus-protocol.rst
MAINTAINERS
drivers/i2c/algos/i2c-algo-bit.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-aspeed.c
drivers/i2c/busses/i2c-au1550.c
drivers/i2c/busses/i2c-bcm2835.c
drivers/i2c/busses/i2c-cadence.c
drivers/i2c/busses/i2c-designware-common.c
drivers/i2c/busses/i2c-designware-core.h
drivers/i2c/busses/i2c-designware-master.c
drivers/i2c/busses/i2c-designware-slave.c
drivers/i2c/busses/i2c-gpio.c
drivers/i2c/busses/i2c-gxp.c [new file with mode: 0644]
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-ls2x.c [new file with mode: 0644]
drivers/i2c/busses/i2c-mt65xx.c
drivers/i2c/busses/i2c-qcom-cci.c
drivers/i2c/busses/i2c-qcom-geni.c
drivers/i2c/busses/i2c-st.c
drivers/i2c/busses/i2c-xiic.c
drivers/i2c/i2c-core-base.c
drivers/i2c/i2c-dev.c
include/linux/pinctrl/devinfo.h
include/linux/platform_data/i2c-gpio.h

diff --git a/Documentation/devicetree/bindings/i2c/hpe,gxp-i2c.yaml b/Documentation/devicetree/bindings/i2c/hpe,gxp-i2c.yaml
new file mode 100644 (file)
index 0000000..6604dcd
--- /dev/null
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/i2c/hpe,gxp-i2c.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: HPE GXP SoC I2C Controller
+
+maintainers:
+  - Nick Hawkins <nick.hawkins@hpe.com>
+
+allOf:
+  - $ref: /schemas/i2c/i2c-controller.yaml#
+
+properties:
+  compatible:
+    const: hpe,gxp-i2c
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clock-frequency:
+    default: 100000
+
+  hpe,sysreg:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      Phandle to the global status and enable interrupt registers shared
+      between each I2C engine controller instance. It enables the I2C
+      engine controller to act as both a master or slave by being able to
+      arm and respond to interrupts from its engine. Each bit in the
+      registers represent the respective bit position.
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    i2c@2600 {
+        compatible = "hpe,gxp-i2c";
+        reg = <0x2500 0x70>;
+        interrupts = <9>;
+        #address-cells = <1>;
+        #size-cells = <0>;
+        hpe,sysreg = <&sysreg_system_controller>;
+        clock-frequency = <10000>;
+
+        eeprom@50 {
+            compatible = "atmel,24c128";
+            reg = <0x50>;
+        };
+    };
index e0d76d5eb1031c4fb64d520dab3f7787870fe4b5..afd4925c2a7d93bb5900b2765fa58d46926656e0 100644 (file)
@@ -33,6 +33,10 @@ properties:
       open drain.
     maxItems: 1
 
+  i2c-gpio,sda-output-only:
+    description: sda as output only
+    type: boolean
+
   i2c-gpio,scl-output-only:
     description: scl as output only
     type: boolean
@@ -63,6 +67,28 @@ properties:
       GPIO line used for SCL into open drain mode, and that something is not
       the GPIO chip. It is essentially an inconsistency flag.
 
+  i2c-gpio,sda-has-no-pullup:
+    type: boolean
+    description: sda is used in a non-compliant way and has no pull-up.
+      Therefore disable open-drain. This property is mutually-exclusive
+      with i2c-gpio,sda-open-drain.
+
+  i2c-gpio,scl-has-no-pullup:
+    type: boolean
+    description: scl is used in a non-compliant way and has no pull-up.
+      Therefore disable open-drain. This property is mutually-exclusive
+      with i2c-gpio,scl-open-drain.
+
+dependencies:
+  i2c-gpio,sda-has-no-pullup:
+    not:
+      required:
+        - i2c-gpio,sda-open-drain
+  i2c-gpio,scl-has-no-pullup:
+    not:
+      required:
+        - i2c-gpio,scl-open-drain
+
 required:
   - compatible
   - sda-gpios
index 421563bf576cd5ca064a617f6d29c9c8508b1f45..72ae2e01cf220972c4311ca8fcc2a0ce3fcab04b 100644 (file)
@@ -41,6 +41,10 @@ properties:
               - mediatek,mt6797-i2c
               - mediatek,mt7623-i2c
           - const: mediatek,mt6577-i2c
+      - items:
+          - enum:
+              - mediatek,mt8365-i2c
+          - const: mediatek,mt8168-i2c
       - items:
           - enum:
               - mediatek,mt8195-i2c
diff --git a/Documentation/devicetree/bindings/i2c/i2c-st.txt b/Documentation/devicetree/bindings/i2c/i2c-st.txt
deleted file mode 100644 (file)
index 4c26fda..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-ST SSC binding, for I2C mode operation
-
-Required properties :
-- compatible : Must be "st,comms-ssc-i2c" or "st,comms-ssc4-i2c"
-- reg : Offset and length of the register set for the device
-- interrupts : the interrupt specifier
-- clock-names: Must contain "ssc".
-- clocks: Must contain an entry for each name in clock-names. See the common
-  clock bindings.
-- A pinctrl state named "default" must be defined to set pins in mode of
-  operation for I2C transfer.
-
-Optional properties :
-- clock-frequency : Desired I2C bus clock frequency in Hz. If not specified,
-  the default 100 kHz frequency will be used. As only Normal and Fast modes
-  are supported, possible values are 100000 and 400000.
-- st,i2c-min-scl-pulse-width-us : The minimum valid SCL pulse width that is
-  allowed through the deglitch circuit. In units of us.
-- st,i2c-min-sda-pulse-width-us : The minimum valid SDA pulse width that is
-  allowed through the deglitch circuit. In units of us.
-- A pinctrl state named "idle" could be defined to set pins in idle state
-  when I2C instance is not performing a transfer.
-- A pinctrl state named "sleep" could be defined to set pins in sleep state
-  when driver enters in suspend.
-
-
-
-Example :
-
-i2c0: i2c@fed40000 {
-       compatible      = "st,comms-ssc4-i2c";
-       reg             = <0xfed40000 0x110>;
-       interrupts      =  <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
-       clocks          = <&clk_s_a0_ls CLK_ICN_REG>;
-       clock-names     = "ssc";
-       clock-frequency = <400000>;
-       pinctrl-names   = "default";
-       pinctrl-0       = <&pinctrl_i2c0_default>;
-       st,i2c-min-scl-pulse-width-us = <0>;
-       st,i2c-min-sda-pulse-width-us = <5>;
-};
diff --git a/Documentation/devicetree/bindings/i2c/loongson,ls2x-i2c.yaml b/Documentation/devicetree/bindings/i2c/loongson,ls2x-i2c.yaml
new file mode 100644 (file)
index 0000000..67882ec
--- /dev/null
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/i2c/loongson,ls2x-i2c.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Loongson LS2X I2C Controller
+
+maintainers:
+  - Binbin Zhou <zhoubinbin@loongson.cn>
+
+allOf:
+  - $ref: /schemas/i2c/i2c-controller.yaml#
+
+properties:
+  compatible:
+    enum:
+      - loongson,ls2k-i2c
+      - loongson,ls7a-i2c
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    i2c0: i2c@1fe21000 {
+        compatible = "loongson,ls2k-i2c";
+        reg = <0x1fe21000 0x8>;
+        interrupt-parent = <&extioiic>;
+        interrupts = <22 IRQ_TYPE_LEVEL_LOW>;
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        eeprom@57 {
+            compatible = "atmel,24c16";
+            reg = <0x57>;
+            pagesize = <16>;
+        };
+    };
index cf9f8fda595fc326dd91857e6ec7929ebe599aad..ec79b7270437f829be2d8985b2b3271ef354108e 100644 (file)
@@ -12,14 +12,24 @@ maintainers:
 
 properties:
   compatible:
-    enum:
-      - qcom,msm8226-cci
-      - qcom,msm8916-cci
-      - qcom,msm8974-cci
-      - qcom,msm8996-cci
-      - qcom,sdm845-cci
-      - qcom,sm8250-cci
-      - qcom,sm8450-cci
+    oneOf:
+      - enum:
+          - qcom,msm8226-cci
+          - qcom,msm8974-cci
+          - qcom,msm8996-cci
+
+      - items:
+          - enum:
+              - qcom,msm8916-cci
+          - const: qcom,msm8226-cci # CCI v1
+
+      - items:
+          - enum:
+              - qcom,sdm845-cci
+              - qcom,sm6350-cci
+              - qcom,sm8250-cci
+              - qcom,sm8450-cci
+          - const: qcom,msm8996-cci # CCI v2
 
   "#address-cells":
     const: 1
@@ -88,10 +98,12 @@ allOf:
   - if:
       properties:
         compatible:
-          contains:
-            enum:
-              - qcom,msm8226-cci
-              - qcom,msm8974-cci
+          oneOf:
+            - contains:
+                enum:
+                  - qcom,msm8974-cci
+
+            - const: qcom,msm8226-cci
     then:
       properties:
         clocks:
@@ -105,10 +117,12 @@ allOf:
   - if:
       properties:
         compatible:
-          contains:
-            enum:
-              - qcom,msm8916-cci
-              - qcom,msm8996-cci
+          oneOf:
+            - contains:
+                enum:
+                  - qcom,msm8916-cci
+
+            - const: qcom,msm8996-cci
     then:
       properties:
         clocks:
@@ -126,6 +140,7 @@ allOf:
           contains:
             enum:
               - qcom,sdm845-cci
+              - qcom,sm6350-cci
     then:
       properties:
         clocks:
@@ -169,7 +184,7 @@ examples:
 
     cci@ac4a000 {
         reg = <0x0ac4a000 0x4000>;
-        compatible = "qcom,sdm845-cci";
+        compatible = "qcom,sdm845-cci", "qcom,msm8996-cci";
         #address-cells = <1>;
         #size-cells = <0>;
 
index c76131902b77b5afadfe6eb52b49347a89dd1fd3..4bbe9e775da13e890aa3bca0c38e33e299d06a77 100644 (file)
@@ -29,6 +29,9 @@ properties:
     minimum: 100000
     maximum: 400000
 
+  resets:
+    maxItems: 1
+
 required:
   - compatible
   - reg
index ddde08636ab0765cbe4f6c7b7673906166e43600..5abf496edb597c0d083013cb6d77f88beb80233b 100644 (file)
@@ -29,6 +29,9 @@ properties:
     minimum: 100000
     maximum: 400000
 
+  resets:
+    maxItems: 1
+
 required:
   - compatible
   - reg
diff --git a/Documentation/devicetree/bindings/i2c/st,sti-i2c.yaml b/Documentation/devicetree/bindings/i2c/st,sti-i2c.yaml
new file mode 100644 (file)
index 0000000..08f9c1e
--- /dev/null
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/i2c/st,sti-i2c.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: I2C controller embedded in STMicroelectronics STi platform
+
+maintainers:
+  - Patrice Chotard <patrice.chotard@foss.st.com>
+
+allOf:
+  - $ref: /schemas/i2c/i2c-controller.yaml#
+
+properties:
+  compatible:
+    enum:
+      - st,comms-ssc-i2c
+      - st,comms-ssc4-i2c
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    maxItems: 1
+
+  clock-frequency:
+    enum: [ 100000, 400000 ]
+    default: 100000
+
+  st,i2c-min-scl-pulse-width-us:
+    description:
+      The minimum valid SCL pulse width that is allowed through the
+      deglitch circuit. In units of us.
+
+  st,i2c-min-sda-pulse-width-us:
+    description:
+      The minimum valid SDA pulse width that is allowed through the
+      deglitch circuit. In units of us.
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/stih407-clks.h>
+    i2c@fed40000 {
+        compatible = "st,comms-ssc4-i2c";
+        reg = <0xfed40000 0x110>;
+        interrupts =  <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+        clocks = <&clk_s_a0_ls CLK_ICN_REG>;
+        clock-names = "ssc";
+        clock-frequency = <400000>;
+        pinctrl-names = "default";
+        pinctrl-0 = <&pinctrl_i2c0_default>;
+        st,i2c-min-scl-pulse-width-us = <0>;
+        st,i2c-min-sda-pulse-width-us = <5>;
+    };
index 8d241a703d855d658ea44f0424b47e55d4183e19..1b598638d4578be74ff04c05f0193019ba2d3e81 100644 (file)
@@ -14,7 +14,9 @@ allOf:
 
 properties:
   compatible:
-    const: xlnx,xps-iic-2.00.a
+    enum:
+      - xlnx,axi-iic-2.1
+      - xlnx,xps-iic-2.00.a
 
   reg:
     maxItems: 1
@@ -30,6 +32,13 @@ properties:
     description: |
       Input clock name.
 
+  clock-frequency:
+    description:
+      Optional I2C SCL clock frequency. If not specified, do not configure
+      in software, rely only on hardware design value.
+    default: 100000
+    enum: [ 100000, 400000, 1000000 ]
+
 required:
   - compatible
   - reg
index 9dca6ec7d2661542f5463a4d921a972054295dc2..91d23889abd503de02264d4748cc5e01343f67ba 100644 (file)
@@ -93,7 +93,7 @@ bus arbitration against another master in a multi-master setup.
 ------------------
 
 This file is write only and you need to write the duration of the arbitration
-intereference (in Âµs, maximum is 100ms). The calling process will then sleep
+interference (in Âµs, maximum is 100ms). The calling process will then sleep
 and wait for the next bus clock. The process is interruptible, though.
 
 Arbitration lost is achieved by waiting for SCL going down by the master under
index 4942c4cad4adabde16cc24ee82dc219b2dd38a40..adc87456c99d217138650d7d527d454d2a4c33b6 100644 (file)
@@ -238,7 +238,7 @@ This is implemented in the following way in the Linux kernel:
 * I2C bus drivers trigger SMBus Host Notify by a call to
   i2c_handle_smbus_host_notify().
 * I2C drivers for devices which can trigger SMBus Host Notify will have
-  client->irq assigned to a Host Notify IRQ if noone else specified an other.
+  client->irq assigned to a Host Notify IRQ if no one else specified another.
 
 There is currently no way to retrieve the data parameter from the client.
 
index 88f9a88f430131eaf0119c5655fbd2e400fc9030..461f6a66354644c9be8510015fadf153e969f270 100644 (file)
@@ -2240,6 +2240,7 @@ S:        Maintained
 F:     Documentation/hwmon/gxp-fan-ctrl.rst
 F:     Documentation/devicetree/bindings/arm/hpe,gxp.yaml
 F:     Documentation/devicetree/bindings/hwmon/hpe,gxp-fan-ctrl.yaml
+F:     Documentation/devicetree/bindings/i2c/hpe,gxp-i2c.yaml
 F:     Documentation/devicetree/bindings/spi/hpe,gxp-spifi.yaml
 F:     Documentation/devicetree/bindings/timer/hpe,gxp-timer.yaml
 F:     arch/arm/boot/dts/hpe-bmc*
@@ -2247,6 +2248,7 @@ F:        arch/arm/boot/dts/hpe-gxp*
 F:     arch/arm/mach-hpe/
 F:     drivers/clocksource/timer-gxp.c
 F:     drivers/hwmon/gxp-fan-ctrl.c
+F:     drivers/i2c/busses/i2c-gxp.c
 F:     drivers/spi/spi-gxp.c
 F:     drivers/watchdog/gxp-wdt.c
 
@@ -2795,7 +2797,7 @@ L:        linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 W:     http://www.stlinux.com
 F:     Documentation/devicetree/bindings/spi/st,ssc-spi.yaml
-F:     Documentation/devicetree/bindings/i2c/i2c-st.txt
+F:     Documentation/devicetree/bindings/i2c/st,sti-i2c.yaml
 F:     arch/arm/boot/dts/sti*
 F:     arch/arm/mach-sti/
 F:     drivers/ata/ahci_st.c
@@ -12097,6 +12099,13 @@ F:     drivers/*/*loongarch*
 F:     Documentation/loongarch/
 F:     Documentation/translations/zh_CN/loongarch/
 
+LOONGSON LS2X I2C DRIVER
+M:     Binbin Zhou <zhoubinbin@loongson.cn>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/i2c/loongson,ls2x-i2c.yaml
+F:     drivers/i2c/busses/i2c-ls2x.c
+
 LOONGSON-2 SOC SERIES GUTS DRIVER
 M:     Yinbo Zhu <zhuyinbo@loongson.cn>
 L:     loongarch@lists.linux.dev
index fc90293afcbf3fc0d8ef0a975278681cf73977e6..eddf25b90ca8d66f01eb21a047e00700d660fa64 100644 (file)
@@ -184,8 +184,9 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)
 
        /* read ack: SDA should be pulled down by slave, or it may
         * NAK (usually to report problems with the data we wrote).
+        * Always report ACK if SDA is write-only.
         */
-       ack = !getsda(adap);    /* ack: sda is pulled low -> success */
+       ack = !adap->getsda || !getsda(adap);    /* ack: sda is pulled low -> success */
        bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c,
                ack ? "A" : "NA");
 
@@ -238,71 +239,55 @@ static int test_bus(struct i2c_adapter *i2c_adap)
                        return -ENODEV;
        }
 
+       if (adap->getsda == NULL)
+               pr_info("%s: SDA is write-only, testing not possible\n", name);
        if (adap->getscl == NULL)
-               pr_info("%s: Testing SDA only, SCL is not readable\n", name);
+               pr_info("%s: SCL is write-only, testing not possible\n", name);
 
-       sda = getsda(adap);
-       scl = (adap->getscl == NULL) ? 1 : getscl(adap);
+       sda = adap->getsda ? getsda(adap) : 1;
+       scl = adap->getscl ? getscl(adap) : 1;
        if (!scl || !sda) {
-               printk(KERN_WARNING
-                      "%s: bus seems to be busy (scl=%d, sda=%d)\n",
-                      name, scl, sda);
+               pr_warn("%s: bus seems to be busy (scl=%d, sda=%d)\n", name, scl, sda);
                goto bailout;
        }
 
        sdalo(adap);
-       sda = getsda(adap);
-       scl = (adap->getscl == NULL) ? 1 : getscl(adap);
-       if (sda) {
-               printk(KERN_WARNING "%s: SDA stuck high!\n", name);
+       if (adap->getsda && getsda(adap)) {
+               pr_warn("%s: SDA stuck high!\n", name);
                goto bailout;
        }
-       if (!scl) {
-               printk(KERN_WARNING
-                      "%s: SCL unexpected low while pulling SDA low!\n",
-                      name);
+       if (adap->getscl && !getscl(adap)) {
+               pr_warn("%s: SCL unexpected low while pulling SDA low!\n", name);
                goto bailout;
        }
 
        sdahi(adap);
-       sda = getsda(adap);
-       scl = (adap->getscl == NULL) ? 1 : getscl(adap);
-       if (!sda) {
-               printk(KERN_WARNING "%s: SDA stuck low!\n", name);
+       if (adap->getsda && !getsda(adap)) {
+               pr_warn("%s: SDA stuck low!\n", name);
                goto bailout;
        }
-       if (!scl) {
-               printk(KERN_WARNING
-                      "%s: SCL unexpected low while pulling SDA high!\n",
-                      name);
+       if (adap->getscl && !getscl(adap)) {
+               pr_warn("%s: SCL unexpected low while pulling SDA high!\n", name);
                goto bailout;
        }
 
        scllo(adap);
-       sda = getsda(adap);
-       scl = (adap->getscl == NULL) ? 0 : getscl(adap);
-       if (scl) {
-               printk(KERN_WARNING "%s: SCL stuck high!\n", name);
+       if (adap->getscl && getscl(adap)) {
+               pr_warn("%s: SCL stuck high!\n", name);
                goto bailout;
        }
-       if (!sda) {
-               printk(KERN_WARNING
-                      "%s: SDA unexpected low while pulling SCL low!\n",
-                      name);
+       if (adap->getsda && !getsda(adap)) {
+               pr_warn("%s: SDA unexpected low while pulling SCL low!\n", name);
                goto bailout;
        }
 
        sclhi(adap);
-       sda = getsda(adap);
-       scl = (adap->getscl == NULL) ? 1 : getscl(adap);
-       if (!scl) {
-               printk(KERN_WARNING "%s: SCL stuck low!\n", name);
+       if (adap->getscl && !getscl(adap)) {
+               pr_warn("%s: SCL stuck low!\n", name);
                goto bailout;
        }
-       if (!sda) {
-               printk(KERN_WARNING
-                      "%s: SDA unexpected low while pulling SCL high!\n",
-                      name);
+       if (adap->getsda && !getsda(adap)) {
+               pr_warn("%s: SDA unexpected low while pulling SCL high!\n", name);
                goto bailout;
        }
 
@@ -420,6 +405,10 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
        unsigned char *temp = msg->buf;
        int count = msg->len;
        const unsigned flags = msg->flags;
+       struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
+
+       if (!adap->getsda)
+               return -EOPNOTSUPP;
 
        while (count > 0) {
                inval = i2c_inb(i2c_adap);
@@ -670,11 +659,15 @@ static int __i2c_bit_add_bus(struct i2c_adapter *adap,
        if (ret < 0)
                return ret;
 
-       /* Complain if SCL can't be read */
-       if (bit_adap->getscl == NULL) {
+       if (bit_adap->getsda == NULL)
+               dev_warn(&adap->dev, "Not I2C compliant: can't read SDA\n");
+
+       if (bit_adap->getscl == NULL)
                dev_warn(&adap->dev, "Not I2C compliant: can't read SCL\n");
+
+       if (bit_adap->getsda == NULL || bit_adap->getscl == NULL)
                dev_warn(&adap->dev, "Bus may be unreliable\n");
-       }
+
        return 0;
 }
 
index d4975444a32db5fa9349ecb63cf80254e3b6757b..9b8e84f20604f436b77494b7ed45bbed7bc53bf5 100644 (file)
@@ -659,6 +659,13 @@ config I2C_GPIO_FAULT_INJECTOR
          faults to an I2C bus, so another bus master can be stress-tested.
          This is for debugging. If unsure, say 'no'.
 
+config I2C_GXP
+       tristate "GXP I2C Interface"
+       depends on ARCH_HPE_GXP || COMPILE_TEST
+       help
+         This enables support for GXP I2C interface. The I2C engines can be
+         either I2C master or I2C slaves.
+
 config I2C_HIGHLANDER
        tristate "Highlander FPGA SMBus interface"
        depends on SH_HIGHLANDER || COMPILE_TEST
@@ -761,6 +768,17 @@ config I2C_LPC2K
          This driver can also be built as a module.  If so, the module
          will be called i2c-lpc2k.
 
+config I2C_LS2X
+       tristate "Loongson LS2X I2C adapter"
+       depends on MACH_LOONGSON64 || COMPILE_TEST
+       help
+         If you say yes to this option, support will be included for the
+         I2C interface on the Loongson-2K SoCs and Loongson LS7A bridge
+         chip.
+
+         This driver can also be built as a module. If so, the module
+         will be called i2c-ls2x.
+
 config I2C_MLXBF
         tristate "Mellanox BlueField I2C controller"
         depends on MELLANOX_PLATFORM && ARM64
index e73cdb1d2b5a85bf0973ee0facc92fe4b76704c4..af56fe2c75c09c791c13cbe78c7e206b7fe06f46 100644 (file)
@@ -77,6 +77,7 @@ obj-$(CONFIG_I2C_IOP3XX)      += i2c-iop3xx.o
 obj-$(CONFIG_I2C_JZ4780)       += i2c-jz4780.o
 obj-$(CONFIG_I2C_KEMPLD)       += i2c-kempld.o
 obj-$(CONFIG_I2C_LPC2K)                += i2c-lpc2k.o
+obj-$(CONFIG_I2C_LS2X)         += i2c-ls2x.o
 obj-$(CONFIG_I2C_MESON)                += i2c-meson.o
 obj-$(CONFIG_I2C_MICROCHIP_CORE)       += i2c-microchip-corei2c.o
 obj-$(CONFIG_I2C_MPC)          += i2c-mpc.o
@@ -127,6 +128,7 @@ obj-$(CONFIG_I2C_THUNDERX)  += i2c-thunderx.o
 obj-$(CONFIG_I2C_XILINX)       += i2c-xiic.o
 obj-$(CONFIG_I2C_XLP9XX)       += i2c-xlp9xx.o
 obj-$(CONFIG_I2C_RCAR)         += i2c-rcar.o
+obj-$(CONFIG_I2C_GXP)          += i2c-gxp.o
 
 # External I2C/SMBus adapter drivers
 obj-$(CONFIG_I2C_DIOLAN_U2C)   += i2c-diolan-u2c.o
index c64c381b69b7f8ce923b0ada0e219561b7198954..d3c99c5b324788da554fcd07a803cd3a4fef9b03 100644 (file)
@@ -979,15 +979,13 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
        const struct of_device_id *match;
        struct aspeed_i2c_bus *bus;
        struct clk *parent_clk;
-       struct resource *res;
        int irq, ret;
 
        bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
        if (!bus)
                return -ENOMEM;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       bus->base = devm_ioremap_resource(&pdev->dev, res);
+       bus->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
        if (IS_ERR(bus->base))
                return PTR_ERR(bus->base);
 
index 99bd24d0e6a59e0741a744c85bda408ad2891510..7b42d35b1294253dbb2e35725f627bc9f5116fc6 100644 (file)
@@ -302,7 +302,6 @@ static int
 i2c_au1550_probe(struct platform_device *pdev)
 {
        struct i2c_au1550_data *priv;
-       struct resource *r;
        int ret;
 
        priv = devm_kzalloc(&pdev->dev, sizeof(struct i2c_au1550_data),
@@ -310,8 +309,7 @@ i2c_au1550_probe(struct platform_device *pdev)
        if (!priv)
                return -ENOMEM;
 
-       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       priv->psc_base = devm_ioremap_resource(&pdev->dev, r);
+       priv->psc_base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
        if (IS_ERR(priv->psc_base))
                return PTR_ERR(priv->psc_base);
 
index f72c6576d8a36b4bcb522853b475ffc7601e3115..09a077b31bfe1759305b8a3cabfd2fbf84871377 100644 (file)
@@ -407,7 +407,6 @@ static const struct i2c_adapter_quirks bcm2835_i2c_quirks = {
 static int bcm2835_i2c_probe(struct platform_device *pdev)
 {
        struct bcm2835_i2c_dev *i2c_dev;
-       struct resource *mem;
        int ret;
        struct i2c_adapter *adap;
        struct clk *mclk;
@@ -420,8 +419,7 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
        i2c_dev->dev = &pdev->dev;
        init_completion(&i2c_dev->completion);
 
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       i2c_dev->regs = devm_ioremap_resource(&pdev->dev, mem);
+       i2c_dev->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
        if (IS_ERR(i2c_dev->regs))
                return PTR_ERR(i2c_dev->regs);
 
index f58943cb134147b3e34111f9545570a301032eca..b5d22e7282c227a1fb29d8dc43dc2bc3aacf8779 100644 (file)
 #define CNDS_I2C_PM_TIMEOUT            1000    /* ms */
 
 #define CDNS_I2C_FIFO_DEPTH            16
-/* FIFO depth at which the DATA interrupt occurs */
-#define CDNS_I2C_DATA_INTR_DEPTH       (CDNS_I2C_FIFO_DEPTH - 2)
 #define CDNS_I2C_MAX_TRANSFER_SIZE     255
 /* Transfer size in multiples of data interrupt depth */
 #define CDNS_I2C_TRANSFER_SIZE (CDNS_I2C_MAX_TRANSFER_SIZE - 3)
@@ -175,7 +173,6 @@ enum cdns_i2c_slave_state {
  * @send_count:                Number of bytes still expected to send
  * @recv_count:                Number of bytes still expected to receive
  * @curr_recv_count:   Number of bytes to be received in current transfer
- * @irq:               IRQ number
  * @input_clk:         Input clock to I2C controller
  * @i2c_clk:           Maximum I2C clock speed
  * @bus_hold_flag:     Flag used in repeated start for clearing HOLD bit
@@ -200,7 +197,6 @@ struct cdns_i2c {
        unsigned int send_count;
        unsigned int recv_count;
        unsigned int curr_recv_count;
-       int irq;
        unsigned long input_clk;
        unsigned int i2c_clk;
        unsigned int bus_hold_flag;
@@ -616,9 +612,7 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id)
        }
 
        /* Determine hold_clear based on number of bytes to receive and hold flag */
-       if (!id->bus_hold_flag &&
-           ((id->p_msg->flags & I2C_M_RECV_LEN) != I2C_M_RECV_LEN) &&
-           (id->recv_count <= CDNS_I2C_FIFO_DEPTH)) {
+       if (!id->bus_hold_flag && id->recv_count <= CDNS_I2C_FIFO_DEPTH) {
                if (cdns_i2c_readreg(CDNS_I2C_CR_OFFSET) & CDNS_I2C_CR_HOLD) {
                        hold_clear = true;
                        if (id->quirks & CDNS_I2C_BROKEN_HOLD_BIT)
@@ -1246,7 +1240,7 @@ static int cdns_i2c_probe(struct platform_device *pdev)
 {
        struct resource *r_mem;
        struct cdns_i2c *id;
-       int ret;
+       int ret, irq;
        const struct of_device_id *match;
 
        id = devm_kzalloc(&pdev->dev, sizeof(*id), GFP_KERNEL);
@@ -1277,10 +1271,9 @@ static int cdns_i2c_probe(struct platform_device *pdev)
        if (IS_ERR(id->membase))
                return PTR_ERR(id->membase);
 
-       ret = platform_get_irq(pdev, 0);
-       if (ret < 0)
-               return ret;
-       id->irq = ret;
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
 
        id->adap.owner = THIS_MODULE;
        id->adap.dev.of_node = pdev->dev.of_node;
@@ -1331,10 +1324,10 @@ static int cdns_i2c_probe(struct platform_device *pdev)
                goto err_clk_dis;
        }
 
-       ret = devm_request_irq(&pdev->dev, id->irq, cdns_i2c_isr, 0,
+       ret = devm_request_irq(&pdev->dev, irq, cdns_i2c_isr, 0,
                                 DRIVER_NAME, id);
        if (ret) {
-               dev_err(&pdev->dev, "cannot get irq %d\n", id->irq);
+               dev_err(&pdev->dev, "cannot get irq %d\n", irq);
                goto err_clk_dis;
        }
        cdns_i2c_init(id);
@@ -1344,7 +1337,7 @@ static int cdns_i2c_probe(struct platform_device *pdev)
                goto err_clk_dis;
 
        dev_info(&pdev->dev, "%u kHz mmio %08lx irq %d\n",
-                id->i2c_clk / 1000, (unsigned long)r_mem->start, id->irq);
+                id->i2c_clk / 1000, (unsigned long)r_mem->start, irq);
 
        return 0;
 
index 581e02cc979a06f9ec4700f4e0794ef2e7215082..0dc6b1ce663f747b6747ffa3bde2f3817c7d35ef 100644 (file)
@@ -391,7 +391,7 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
 
 int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
 {
-       u32 reg;
+       unsigned int reg;
        int ret;
 
        ret = i2c_dw_acquire_lock(dev);
@@ -442,7 +442,7 @@ err_release_lock:
 void __i2c_dw_disable(struct dw_i2c_dev *dev)
 {
        int timeout = 100;
-       u32 status;
+       unsigned int status;
 
        do {
                __i2c_dw_disable_nowait(dev);
@@ -465,7 +465,7 @@ void __i2c_dw_disable(struct dw_i2c_dev *dev)
        dev_warn(dev->dev, "timeout in disabling adapter\n");
 }
 
-unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev)
+u32 i2c_dw_clk_rate(struct dw_i2c_dev *dev)
 {
        /*
         * Clock is not necessary if we got LCNT/HCNT values directly from
@@ -527,7 +527,7 @@ void i2c_dw_release_lock(struct dw_i2c_dev *dev)
  */
 int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
 {
-       u32 status;
+       unsigned int status;
        int ret;
 
        ret = regmap_read_poll_timeout(dev->map, DW_IC_STATUS, status,
@@ -571,7 +571,8 @@ int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
 
 int i2c_dw_set_fifo_size(struct dw_i2c_dev *dev)
 {
-       u32 param, tx_fifo_depth, rx_fifo_depth;
+       u32 tx_fifo_depth, rx_fifo_depth;
+       unsigned int param;
        int ret;
 
        /*
@@ -611,7 +612,7 @@ u32 i2c_dw_func(struct i2c_adapter *adap)
 
 void i2c_dw_disable(struct dw_i2c_dev *dev)
 {
-       u32 dummy;
+       unsigned int dummy;
        int ret;
 
        ret = i2c_dw_acquire_lock(dev);
index 95ebc5eaa5d12cf6008e5587996950a67bd20a5e..050d8c63ad3c5464da845a7116a5e577cfb6611e 100644 (file)
@@ -37,6 +37,7 @@
 #define DW_IC_CON_STOP_DET_IFADDRESSED         BIT(7)
 #define DW_IC_CON_TX_EMPTY_CTRL                        BIT(8)
 #define DW_IC_CON_RX_FIFO_FULL_HLD_CTRL                BIT(9)
+#define DW_IC_CON_BUS_CLEAR_CTRL               BIT(11)
 
 #define DW_IC_DATA_CMD_DAT                     GENMASK(7, 0)
 
@@ -264,7 +265,7 @@ struct dw_i2c_dev {
        u8                      *rx_buf;
        int                     msg_err;
        unsigned int            status;
-       u32                     abort_source;
+       unsigned int            abort_source;
        int                     irq;
        u32                     flags;
        struct i2c_adapter      adapter;
@@ -320,7 +321,7 @@ int i2c_dw_init_regmap(struct dw_i2c_dev *dev);
 u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset);
 u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset);
 int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev);
-unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev);
+u32 i2c_dw_clk_rate(struct dw_i2c_dev *dev);
 int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare);
 int i2c_dw_acquire_lock(struct dw_i2c_dev *dev);
 void i2c_dw_release_lock(struct dw_i2c_dev *dev);
index 45f569155bfe1477f681808e0e741646c5d94690..55ea91a6338290c8844076067709f870edfcdcef 100644 (file)
@@ -39,7 +39,7 @@ static void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev)
 
 static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
 {
-       u32 comp_param1;
+       unsigned int comp_param1;
        u32 sda_falling_time, scl_falling_time;
        struct i2c_timings *t = &dev->timings;
        const char *fp_str = "";
@@ -211,7 +211,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
 {
        struct i2c_msg *msgs = dev->msgs;
        u32 ic_con = 0, ic_tar = 0;
-       u32 dummy;
+       unsigned int dummy;
 
        /* Disable the adapter */
        __i2c_dw_disable(dev);
@@ -287,7 +287,7 @@ static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs,
        int msg_wrt_idx, msg_itr_lmt, buf_len, data_idx;
        int cmd = 0, status;
        u8 *tx_buf;
-       u32 val;
+       unsigned int val;
 
        /*
         * In order to enable the interrupt for UCSI i.e. AMD NAVI GPU card,
@@ -505,7 +505,8 @@ i2c_dw_read(struct dw_i2c_dev *dev)
        unsigned int rx_valid;
 
        for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) {
-               u32 len, tmp;
+               unsigned int tmp;
+               u32 len;
                u8 *buf;
 
                if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD))
@@ -653,7 +654,7 @@ static const struct i2c_adapter_quirks i2c_dw_quirks = {
 
 static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
 {
-       u32 stat, dummy;
+       unsigned int stat, dummy;
 
        /*
         * The IC_INTR_STAT register just indicates "enabled" interrupts.
@@ -714,7 +715,7 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
 static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
 {
        struct dw_i2c_dev *dev = dev_id;
-       u32 stat, enabled;
+       unsigned int stat, enabled;
 
        regmap_read(dev->map, DW_IC_ENABLE, &enabled);
        regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &stat);
@@ -865,6 +866,7 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)
 {
        struct i2c_adapter *adap = &dev->adapter;
        unsigned long irq_flags;
+       unsigned int ic_con;
        int ret;
 
        init_completion(&dev->cmd_complete);
@@ -884,6 +886,25 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)
        if (ret)
                return ret;
 
+       /* Lock the bus for accessing DW_IC_CON */
+       ret = i2c_dw_acquire_lock(dev);
+       if (ret)
+               return ret;
+
+       /*
+        * On AMD platforms BIOS advertises the bus clear feature
+        * and enables the SCL/SDA stuck low. SMU FW does the
+        * bus recovery process. Driver should not ignore this BIOS
+        * advertisement of bus clear feature.
+        */
+       ret = regmap_read(dev->map, DW_IC_CON, &ic_con);
+       i2c_dw_release_lock(dev);
+       if (ret)
+               return ret;
+
+       if (ic_con & DW_IC_CON_BUS_CLEAR_CTRL)
+               dev->master_cfg |= DW_IC_CON_BUS_CLEAR_CTRL;
+
        ret = dev->init(dev);
        if (ret)
                return ret;
index c6d2e4c2ac23c9021171ec4f2c3ca6036f6e6c45..cec25054bb244fadd946d36dc234d499aa831260 100644 (file)
@@ -98,7 +98,7 @@ static int i2c_dw_unreg_slave(struct i2c_client *slave)
 
 static u32 i2c_dw_read_clear_intrbits_slave(struct dw_i2c_dev *dev)
 {
-       u32 stat, dummy;
+       unsigned int stat, dummy;
 
        /*
         * The IC_INTR_STAT register just indicates "enabled" interrupts.
@@ -150,7 +150,7 @@ static u32 i2c_dw_read_clear_intrbits_slave(struct dw_i2c_dev *dev)
 static irqreturn_t i2c_dw_isr_slave(int this_irq, void *dev_id)
 {
        struct dw_i2c_dev *dev = dev_id;
-       u32 raw_stat, stat, enabled, tmp;
+       unsigned int raw_stat, stat, enabled, tmp;
        u8 val = 0, slave_activity;
 
        regmap_read(dev->map, DW_IC_ENABLE, &enabled);
index 0e4385a9bcf71c902345163298cf6f4734f3d5e6..1794c0399f22d453127dbe1af6f36e694c3f6768 100644 (file)
@@ -13,9 +13,9 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
-#include <linux/of.h>
 #include <linux/platform_data/i2c-gpio.h>
 #include <linux/platform_device.h>
+#include <linux/property.h>
 #include <linux/slab.h>
 
 struct i2c_gpio_private_data {
@@ -300,22 +300,29 @@ static inline void i2c_gpio_fault_injector_init(struct platform_device *pdev) {}
 static inline void i2c_gpio_fault_injector_exit(struct platform_device *pdev) {}
 #endif /* CONFIG_I2C_GPIO_FAULT_INJECTOR*/
 
-static void of_i2c_gpio_get_props(struct device_node *np,
-                                 struct i2c_gpio_platform_data *pdata)
+/* Get i2c-gpio properties from DT or ACPI table */
+static void i2c_gpio_get_properties(struct device *dev,
+                                   struct i2c_gpio_platform_data *pdata)
 {
        u32 reg;
 
-       of_property_read_u32(np, "i2c-gpio,delay-us", &pdata->udelay);
+       device_property_read_u32(dev, "i2c-gpio,delay-us", &pdata->udelay);
 
-       if (!of_property_read_u32(np, "i2c-gpio,timeout-ms", &reg))
+       if (!device_property_read_u32(dev, "i2c-gpio,timeout-ms", &reg))
                pdata->timeout = msecs_to_jiffies(reg);
 
        pdata->sda_is_open_drain =
-               of_property_read_bool(np, "i2c-gpio,sda-open-drain");
+               device_property_read_bool(dev, "i2c-gpio,sda-open-drain");
        pdata->scl_is_open_drain =
-               of_property_read_bool(np, "i2c-gpio,scl-open-drain");
+               device_property_read_bool(dev, "i2c-gpio,scl-open-drain");
        pdata->scl_is_output_only =
-               of_property_read_bool(np, "i2c-gpio,scl-output-only");
+               device_property_read_bool(dev, "i2c-gpio,scl-output-only");
+       pdata->sda_is_output_only =
+               device_property_read_bool(dev, "i2c-gpio,sda-output-only");
+       pdata->sda_has_no_pullup =
+               device_property_read_bool(dev, "i2c-gpio,sda-has-no-pullup");
+       pdata->scl_has_no_pullup =
+               device_property_read_bool(dev, "i2c-gpio,scl-has-no-pullup");
 }
 
 static struct gpio_desc *i2c_gpio_get_desc(struct device *dev,
@@ -361,7 +368,7 @@ static int i2c_gpio_probe(struct platform_device *pdev)
        struct i2c_algo_bit_data *bit_data;
        struct i2c_adapter *adap;
        struct device *dev = &pdev->dev;
-       struct device_node *np = dev->of_node;
+       struct fwnode_handle *fwnode = dev_fwnode(dev);
        enum gpiod_flags gflags;
        int ret;
 
@@ -373,8 +380,8 @@ static int i2c_gpio_probe(struct platform_device *pdev)
        bit_data = &priv->bit_data;
        pdata = &priv->pdata;
 
-       if (np) {
-               of_i2c_gpio_get_props(np, pdata);
+       if (fwnode) {
+               i2c_gpio_get_properties(dev, pdata);
        } else {
                /*
                 * If all platform data settings are zero it is OK
@@ -392,7 +399,7 @@ static int i2c_gpio_probe(struct platform_device *pdev)
         * handle them as we handle any other output. Else we enforce open
         * drain as this is required for an I2C bus.
         */
-       if (pdata->sda_is_open_drain)
+       if (pdata->sda_is_open_drain || pdata->sda_has_no_pullup)
                gflags = GPIOD_OUT_HIGH;
        else
                gflags = GPIOD_OUT_HIGH_OPEN_DRAIN;
@@ -400,7 +407,7 @@ static int i2c_gpio_probe(struct platform_device *pdev)
        if (IS_ERR(priv->sda))
                return PTR_ERR(priv->sda);
 
-       if (pdata->scl_is_open_drain)
+       if (pdata->scl_is_open_drain || pdata->scl_has_no_pullup)
                gflags = GPIOD_OUT_HIGH;
        else
                gflags = GPIOD_OUT_HIGH_OPEN_DRAIN;
@@ -418,7 +425,8 @@ static int i2c_gpio_probe(struct platform_device *pdev)
 
        if (!pdata->scl_is_output_only)
                bit_data->getscl = i2c_gpio_getscl;
-       bit_data->getsda = i2c_gpio_getsda;
+       if (!pdata->sda_is_output_only)
+               bit_data->getsda = i2c_gpio_getsda;
 
        if (pdata->udelay)
                bit_data->udelay = pdata->udelay;
@@ -435,7 +443,7 @@ static int i2c_gpio_probe(struct platform_device *pdev)
        bit_data->data = priv;
 
        adap->owner = THIS_MODULE;
-       if (np)
+       if (fwnode)
                strscpy(adap->name, dev_name(dev), sizeof(adap->name));
        else
                snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
@@ -443,7 +451,7 @@ static int i2c_gpio_probe(struct platform_device *pdev)
        adap->algo_data = bit_data;
        adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
        adap->dev.parent = dev;
-       adap->dev.of_node = np;
+       device_set_node(&adap->dev, fwnode);
 
        adap->nr = pdev->id;
        ret = i2c_bit_add_numbered_bus(adap);
@@ -489,10 +497,17 @@ static const struct of_device_id i2c_gpio_dt_ids[] = {
 
 MODULE_DEVICE_TABLE(of, i2c_gpio_dt_ids);
 
+static const struct acpi_device_id i2c_gpio_acpi_match[] = {
+       { "LOON0005" }, /* LoongArch */
+       { }
+};
+MODULE_DEVICE_TABLE(acpi, i2c_gpio_acpi_match);
+
 static struct platform_driver i2c_gpio_driver = {
        .driver         = {
                .name   = "i2c-gpio",
                .of_match_table = i2c_gpio_dt_ids,
+               .acpi_match_table = i2c_gpio_acpi_match,
        },
        .probe          = i2c_gpio_probe,
        .remove         = i2c_gpio_remove,
diff --git a/drivers/i2c/busses/i2c-gxp.c b/drivers/i2c/busses/i2c-gxp.c
new file mode 100644 (file)
index 0000000..da4c8e5
--- /dev/null
@@ -0,0 +1,620 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2022 Hewlett-Packard Enterprise Development Company, L.P. */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#define GXP_MAX_I2C_ENGINE 10
+static const char * const gxp_i2c_name[] = {
+       "gxp-i2c0", "gxp-i2c1", "gxp-i2c2", "gxp-i2c3",
+       "gxp-i2c4", "gxp-i2c5", "gxp-i2c6", "gxp-i2c7",
+       "gxp-i2c8", "gxp-i2c9" };
+
+/* GXP I2C Global interrupt status/enable register*/
+#define GXP_I2CINTSTAT         0x00
+#define GXP_I2CINTEN           0x04
+
+/* GXP I2C registers */
+#define GXP_I2CSTAT            0x00
+#define MASK_STOP_EVENT                0x20
+#define MASK_ACK               0x08
+#define MASK_RW                        0x04
+#define GXP_I2CEVTERR          0x01
+#define MASK_SLAVE_CMD_EVENT   0x01
+#define MASK_SLAVE_DATA_EVENT  0x02
+#define MASK_MASTER_EVENT      0x10
+#define GXP_I2CSNPDAT          0x02
+#define GXP_I2CMCMD            0x04
+#define GXP_I2CSCMD            0x06
+#define GXP_I2CSNPAA           0x09
+#define GXP_I2CADVFEAT         0x0A
+#define GXP_I2COWNADR          0x0B
+#define GXP_I2CFREQDIV         0x0C
+#define GXP_I2CFLTFAIR         0x0D
+#define GXP_I2CTMOEDG          0x0E
+#define GXP_I2CCYCTIM          0x0F
+
+/* I2CSCMD Bits */
+#define SNOOP_EVT_CLR          0x80
+#define SLAVE_EVT_CLR          0x40
+#define        SNOOP_EVT_MASK          0x20
+#define SLAVE_EVT_MASK         0x10
+#define SLAVE_ACK_ENAB         0x08
+#define SLAVE_EVT_STALL                0x01
+
+/* I2CMCMD Bits */
+#define MASTER_EVT_CLR         0x80
+#define MASTER_ACK_ENAB                0x08
+#define RW_CMD                 0x04
+#define STOP_CMD               0x02
+#define START_CMD              0x01
+
+/* I2CTMOEDG value */
+#define GXP_DATA_EDGE_RST_CTRL 0x0a /* 30ns */
+
+/* I2CFLTFAIR Bits */
+#define FILTER_CNT             0x30
+#define FAIRNESS_CNT           0x02
+
+enum {
+       GXP_I2C_IDLE = 0,
+       GXP_I2C_ADDR_PHASE,
+       GXP_I2C_RDATA_PHASE,
+       GXP_I2C_WDATA_PHASE,
+       GXP_I2C_ADDR_NACK,
+       GXP_I2C_DATA_NACK,
+       GXP_I2C_ERROR,
+       GXP_I2C_COMP
+};
+
+struct gxp_i2c_drvdata {
+       struct device *dev;
+       void __iomem *base;
+       struct i2c_timings t;
+       u32 engine;
+       int irq;
+       struct completion completion;
+       struct i2c_adapter adapter;
+       struct i2c_msg *curr_msg;
+       int msgs_remaining;
+       int msgs_num;
+       u8 *buf;
+       size_t buf_remaining;
+       unsigned char state;
+       struct i2c_client *slave;
+       unsigned char stopped;
+};
+
+static struct regmap *i2cg_map;
+
+static void gxp_i2c_start(struct gxp_i2c_drvdata *drvdata)
+{
+       u16 value;
+
+       drvdata->buf = drvdata->curr_msg->buf;
+       drvdata->buf_remaining = drvdata->curr_msg->len;
+
+       /* Note: Address in struct i2c_msg is 7 bits */
+       value = drvdata->curr_msg->addr << 9;
+
+       /* Read or Write */
+       value |= drvdata->curr_msg->flags & I2C_M_RD ? RW_CMD | START_CMD : START_CMD;
+
+       drvdata->state = GXP_I2C_ADDR_PHASE;
+       writew(value, drvdata->base + GXP_I2CMCMD);
+}
+
+static int gxp_i2c_master_xfer(struct i2c_adapter *adapter,
+                              struct i2c_msg *msgs, int num)
+{
+       int ret;
+       struct gxp_i2c_drvdata *drvdata = i2c_get_adapdata(adapter);
+       unsigned long time_left;
+
+       drvdata->msgs_remaining = num;
+       drvdata->curr_msg = msgs;
+       drvdata->msgs_num = num;
+       reinit_completion(&drvdata->completion);
+
+       gxp_i2c_start(drvdata);
+
+       time_left = wait_for_completion_timeout(&drvdata->completion,
+                                               adapter->timeout);
+       ret = num - drvdata->msgs_remaining;
+       if (time_left == 0) {
+               switch (drvdata->state) {
+               case GXP_I2C_WDATA_PHASE:
+                       break;
+               case GXP_I2C_RDATA_PHASE:
+                       break;
+               case GXP_I2C_ADDR_PHASE:
+                       break;
+               default:
+                       break;
+               }
+               return -ETIMEDOUT;
+       }
+
+       if (drvdata->state == GXP_I2C_ADDR_NACK ||
+           drvdata->state == GXP_I2C_DATA_NACK)
+               return -EIO;
+
+       return ret;
+}
+
+static u32 gxp_i2c_func(struct i2c_adapter *adap)
+{
+       if (IS_ENABLED(CONFIG_I2C_SLAVE))
+               return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SLAVE;
+
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+static int gxp_i2c_reg_slave(struct i2c_client *slave)
+{
+       struct gxp_i2c_drvdata *drvdata = i2c_get_adapdata(slave->adapter);
+
+       if (drvdata->slave)
+               return -EBUSY;
+
+       if (slave->flags & I2C_CLIENT_TEN)
+               return -EAFNOSUPPORT;
+
+       drvdata->slave = slave;
+
+       writeb(slave->addr << 1, drvdata->base + GXP_I2COWNADR);
+       writeb(SLAVE_EVT_CLR | SNOOP_EVT_MASK | SLAVE_ACK_ENAB |
+              SLAVE_EVT_STALL, drvdata->base + GXP_I2CSCMD);
+
+       return 0;
+}
+
+static int gxp_i2c_unreg_slave(struct i2c_client *slave)
+{
+       struct gxp_i2c_drvdata *drvdata = i2c_get_adapdata(slave->adapter);
+
+       WARN_ON(!drvdata->slave);
+
+       writeb(0x00, drvdata->base + GXP_I2COWNADR);
+       writeb(SNOOP_EVT_CLR | SLAVE_EVT_CLR | SNOOP_EVT_MASK |
+              SLAVE_EVT_MASK, drvdata->base + GXP_I2CSCMD);
+
+       drvdata->slave = NULL;
+
+       return 0;
+}
+#endif
+
+static const struct i2c_algorithm gxp_i2c_algo = {
+       .master_xfer   = gxp_i2c_master_xfer,
+       .functionality = gxp_i2c_func,
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+       .reg_slave     = gxp_i2c_reg_slave,
+       .unreg_slave   = gxp_i2c_unreg_slave,
+#endif
+};
+
+static void gxp_i2c_stop(struct gxp_i2c_drvdata *drvdata)
+{
+       /* Clear event and send stop */
+       writeb(MASTER_EVT_CLR | STOP_CMD, drvdata->base + GXP_I2CMCMD);
+
+       complete(&drvdata->completion);
+}
+
+static void gxp_i2c_restart(struct gxp_i2c_drvdata *drvdata)
+{
+       u16 value;
+
+       drvdata->buf = drvdata->curr_msg->buf;
+       drvdata->buf_remaining = drvdata->curr_msg->len;
+
+       value = drvdata->curr_msg->addr << 9;
+
+       if (drvdata->curr_msg->flags & I2C_M_RD) {
+               /* Read and clear master event */
+               value |= MASTER_EVT_CLR | RW_CMD | START_CMD;
+       } else {
+               /* Write and clear master event */
+               value |= MASTER_EVT_CLR | START_CMD;
+       }
+
+       drvdata->state = GXP_I2C_ADDR_PHASE;
+
+       writew(value, drvdata->base + GXP_I2CMCMD);
+}
+
+static void gxp_i2c_chk_addr_ack(struct gxp_i2c_drvdata *drvdata)
+{
+       u16 value;
+
+       value = readb(drvdata->base + GXP_I2CSTAT);
+       if (!(value & MASK_ACK)) {
+               /* Got no ack, stop */
+               drvdata->state = GXP_I2C_ADDR_NACK;
+               gxp_i2c_stop(drvdata);
+               return;
+       }
+
+       if (drvdata->curr_msg->flags & I2C_M_RD) {
+               /* Start to read data from slave */
+               if (drvdata->buf_remaining == 0) {
+                       /* No more data to read, stop */
+                       drvdata->msgs_remaining--;
+                       drvdata->state = GXP_I2C_COMP;
+                       gxp_i2c_stop(drvdata);
+                       return;
+               }
+               drvdata->state = GXP_I2C_RDATA_PHASE;
+
+               if (drvdata->buf_remaining == 1) {
+                       /* The last data, do not ack */
+                       writeb(MASTER_EVT_CLR | RW_CMD,
+                              drvdata->base + GXP_I2CMCMD);
+               } else {
+                       /* Read data and ack it */
+                       writeb(MASTER_EVT_CLR | MASTER_ACK_ENAB |
+                              RW_CMD, drvdata->base + GXP_I2CMCMD);
+               }
+       } else {
+               /* Start to write first data to slave */
+               if (drvdata->buf_remaining == 0) {
+                       /* No more data to write, stop */
+                       drvdata->msgs_remaining--;
+                       drvdata->state = GXP_I2C_COMP;
+                       gxp_i2c_stop(drvdata);
+                       return;
+               }
+               value = *drvdata->buf;
+               value = value << 8;
+               /* Clear master event */
+               value |= MASTER_EVT_CLR;
+               drvdata->buf++;
+               drvdata->buf_remaining--;
+               drvdata->state = GXP_I2C_WDATA_PHASE;
+               writew(value, drvdata->base + GXP_I2CMCMD);
+       }
+}
+
+static void gxp_i2c_ack_data(struct gxp_i2c_drvdata *drvdata)
+{
+       u8 value;
+
+       /* Store the data returned */
+       value = readb(drvdata->base + GXP_I2CSNPDAT);
+       *drvdata->buf = value;
+       drvdata->buf++;
+       drvdata->buf_remaining--;
+
+       if (drvdata->buf_remaining == 0) {
+               /* No more data, this message is completed. */
+               drvdata->msgs_remaining--;
+
+               if (drvdata->msgs_remaining == 0) {
+                       /* No more messages, stop */
+                       drvdata->state = GXP_I2C_COMP;
+                       gxp_i2c_stop(drvdata);
+                       return;
+               }
+               /* Move to next message and start transfer */
+               drvdata->curr_msg++;
+               gxp_i2c_restart(drvdata);
+               return;
+       }
+
+       /* Ack the slave to make it send next byte */
+       drvdata->state = GXP_I2C_RDATA_PHASE;
+       if (drvdata->buf_remaining == 1) {
+               /* The last data, do not ack */
+               writeb(MASTER_EVT_CLR | RW_CMD,
+                      drvdata->base + GXP_I2CMCMD);
+       } else {
+               /* Read data and ack it */
+               writeb(MASTER_EVT_CLR | MASTER_ACK_ENAB |
+                      RW_CMD, drvdata->base + GXP_I2CMCMD);
+       }
+}
+
+static void gxp_i2c_chk_data_ack(struct gxp_i2c_drvdata *drvdata)
+{
+       u16 value;
+
+       value = readb(drvdata->base + GXP_I2CSTAT);
+       if (!(value & MASK_ACK)) {
+               /* Received No ack, stop */
+               drvdata->state = GXP_I2C_DATA_NACK;
+               gxp_i2c_stop(drvdata);
+               return;
+       }
+
+       /* Got ack, check if there is more data to write */
+       if (drvdata->buf_remaining == 0) {
+               /* No more data, this message is completed */
+               drvdata->msgs_remaining--;
+
+               if (drvdata->msgs_remaining == 0) {
+                       /* No more messages, stop */
+                       drvdata->state = GXP_I2C_COMP;
+                       gxp_i2c_stop(drvdata);
+                       return;
+               }
+               /* Move to next message and start transfer */
+               drvdata->curr_msg++;
+               gxp_i2c_restart(drvdata);
+               return;
+       }
+
+       /* Write data to slave */
+       value = *drvdata->buf;
+       value = value << 8;
+
+       /* Clear master event */
+       value |= MASTER_EVT_CLR;
+       drvdata->buf++;
+       drvdata->buf_remaining--;
+       drvdata->state = GXP_I2C_WDATA_PHASE;
+       writew(value, drvdata->base + GXP_I2CMCMD);
+}
+
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+static bool gxp_i2c_slave_irq_handler(struct gxp_i2c_drvdata *drvdata)
+{
+       u8 value;
+       u8 buf;
+       int ret;
+
+       value = readb(drvdata->base + GXP_I2CEVTERR);
+
+       /* Received start or stop event */
+       if (value & MASK_SLAVE_CMD_EVENT) {
+               value = readb(drvdata->base + GXP_I2CSTAT);
+               /* Master sent stop */
+               if (value & MASK_STOP_EVENT) {
+                       if (drvdata->stopped == 0)
+                               i2c_slave_event(drvdata->slave, I2C_SLAVE_STOP, &buf);
+                       writeb(SLAVE_EVT_CLR | SNOOP_EVT_MASK |
+                              SLAVE_ACK_ENAB | SLAVE_EVT_STALL, drvdata->base + GXP_I2CSCMD);
+                       drvdata->stopped = 1;
+               } else {
+                       /* Master sent start and  wants to read */
+                       drvdata->stopped = 0;
+                       if (value & MASK_RW) {
+                               i2c_slave_event(drvdata->slave,
+                                               I2C_SLAVE_READ_REQUESTED, &buf);
+                               value = buf << 8 | (SLAVE_EVT_CLR | SNOOP_EVT_MASK |
+                                                   SLAVE_EVT_STALL);
+                               writew(value, drvdata->base + GXP_I2CSCMD);
+                       } else {
+                               /* Master wants to write to us */
+                               ret = i2c_slave_event(drvdata->slave,
+                                                     I2C_SLAVE_WRITE_REQUESTED, &buf);
+                               if (!ret) {
+                                       /* Ack next byte from master */
+                                       writeb(SLAVE_EVT_CLR | SNOOP_EVT_MASK |
+                                              SLAVE_ACK_ENAB | SLAVE_EVT_STALL,
+                                              drvdata->base + GXP_I2CSCMD);
+                               } else {
+                                       /* Nack next byte from master */
+                                       writeb(SLAVE_EVT_CLR | SNOOP_EVT_MASK |
+                                              SLAVE_EVT_STALL, drvdata->base + GXP_I2CSCMD);
+                               }
+                       }
+               }
+       } else if (value & MASK_SLAVE_DATA_EVENT) {
+               value = readb(drvdata->base + GXP_I2CSTAT);
+               /* Master wants to read */
+               if (value & MASK_RW) {
+                       /* Master wants another byte */
+                       if (value & MASK_ACK) {
+                               i2c_slave_event(drvdata->slave,
+                                               I2C_SLAVE_READ_PROCESSED, &buf);
+                               value = buf << 8 | (SLAVE_EVT_CLR | SNOOP_EVT_MASK |
+                                                   SLAVE_EVT_STALL);
+                               writew(value, drvdata->base + GXP_I2CSCMD);
+                       } else {
+                               /* No more bytes needed */
+                               writew(SLAVE_EVT_CLR | SNOOP_EVT_MASK |
+                                      SLAVE_ACK_ENAB | SLAVE_EVT_STALL,
+                                      drvdata->base + GXP_I2CSCMD);
+                       }
+               } else {
+                       /* Master wants to write to us */
+                       value = readb(drvdata->base + GXP_I2CSNPDAT);
+                       buf = (uint8_t)value;
+                       ret = i2c_slave_event(drvdata->slave,
+                                             I2C_SLAVE_WRITE_RECEIVED, &buf);
+                       if (!ret) {
+                               /* Ack next byte from master */
+                               writeb(SLAVE_EVT_CLR | SNOOP_EVT_MASK |
+                                      SLAVE_ACK_ENAB | SLAVE_EVT_STALL,
+                                      drvdata->base + GXP_I2CSCMD);
+                       } else {
+                               /* Nack next byte from master */
+                               writeb(SLAVE_EVT_CLR | SNOOP_EVT_MASK |
+                                      SLAVE_EVT_STALL, drvdata->base + GXP_I2CSCMD);
+                       }
+               }
+       } else {
+               return false;
+       }
+
+       return true;
+}
+#endif
+
+static irqreturn_t gxp_i2c_irq_handler(int irq, void *_drvdata)
+{
+       struct gxp_i2c_drvdata *drvdata = (struct gxp_i2c_drvdata *)_drvdata;
+       u32 value;
+
+       /* Check if the interrupt is for the current engine */
+       regmap_read(i2cg_map, GXP_I2CINTSTAT, &value);
+       if (!(value & BIT(drvdata->engine)))
+               return IRQ_NONE;
+
+       value = readb(drvdata->base + GXP_I2CEVTERR);
+
+       /* Error */
+       if (value & ~(MASK_MASTER_EVENT | MASK_SLAVE_CMD_EVENT |
+                               MASK_SLAVE_DATA_EVENT)) {
+               /* Clear all events */
+               writeb(0x00, drvdata->base + GXP_I2CEVTERR);
+               drvdata->state = GXP_I2C_ERROR;
+               gxp_i2c_stop(drvdata);
+               return IRQ_HANDLED;
+       }
+
+       if (IS_ENABLED(CONFIG_I2C_SLAVE)) {
+               /* Slave mode */
+               if (value & (MASK_SLAVE_CMD_EVENT | MASK_SLAVE_DATA_EVENT)) {
+                       if (gxp_i2c_slave_irq_handler(drvdata))
+                               return IRQ_HANDLED;
+                       return IRQ_NONE;
+               }
+       }
+
+       /*  Master mode */
+       switch (drvdata->state) {
+       case GXP_I2C_ADDR_PHASE:
+               gxp_i2c_chk_addr_ack(drvdata);
+               break;
+
+       case GXP_I2C_RDATA_PHASE:
+               gxp_i2c_ack_data(drvdata);
+               break;
+
+       case GXP_I2C_WDATA_PHASE:
+               gxp_i2c_chk_data_ack(drvdata);
+               break;
+       }
+
+       return IRQ_HANDLED;
+}
+
+static void gxp_i2c_init(struct gxp_i2c_drvdata *drvdata)
+{
+       drvdata->state = GXP_I2C_IDLE;
+       writeb(2000000 / drvdata->t.bus_freq_hz,
+              drvdata->base + GXP_I2CFREQDIV);
+       writeb(FILTER_CNT | FAIRNESS_CNT,
+              drvdata->base + GXP_I2CFLTFAIR);
+       writeb(GXP_DATA_EDGE_RST_CTRL, drvdata->base + GXP_I2CTMOEDG);
+       writeb(0x00, drvdata->base + GXP_I2CCYCTIM);
+       writeb(0x00, drvdata->base + GXP_I2CSNPAA);
+       writeb(0x00, drvdata->base + GXP_I2CADVFEAT);
+       writeb(SNOOP_EVT_CLR | SLAVE_EVT_CLR | SNOOP_EVT_MASK |
+              SLAVE_EVT_MASK, drvdata->base + GXP_I2CSCMD);
+       writeb(MASTER_EVT_CLR, drvdata->base + GXP_I2CMCMD);
+       writeb(0x00, drvdata->base + GXP_I2CEVTERR);
+       writeb(0x00, drvdata->base + GXP_I2COWNADR);
+}
+
+static int gxp_i2c_probe(struct platform_device *pdev)
+{
+       struct gxp_i2c_drvdata *drvdata;
+       int rc;
+       struct i2c_adapter *adapter;
+
+       if (!i2cg_map) {
+               i2cg_map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+                                                          "hpe,sysreg");
+               if (IS_ERR(i2cg_map)) {
+                       return dev_err_probe(&pdev->dev, IS_ERR(i2cg_map),
+                                            "failed to map i2cg_handle\n");
+               }
+
+               /* Disable interrupt */
+               regmap_update_bits(i2cg_map, GXP_I2CINTEN, 0x00000FFF, 0);
+       }
+
+       drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata),
+                              GFP_KERNEL);
+       if (!drvdata)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, drvdata);
+       drvdata->dev = &pdev->dev;
+       init_completion(&drvdata->completion);
+
+       drvdata->base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(drvdata->base))
+               return PTR_ERR(drvdata->base);
+
+       /* Use physical memory address to determine which I2C engine this is. */
+       drvdata->engine = ((size_t)drvdata->base & 0xf00) >> 8;
+
+       if (drvdata->engine >= GXP_MAX_I2C_ENGINE) {
+               return dev_err_probe(&pdev->dev, -EINVAL, "i2c engine% is unsupported\n",
+                       drvdata->engine);
+       }
+
+       rc = platform_get_irq(pdev, 0);
+       if (rc < 0)
+               return rc;
+
+       drvdata->irq = rc;
+       rc = devm_request_irq(&pdev->dev, drvdata->irq, gxp_i2c_irq_handler,
+                             IRQF_SHARED, gxp_i2c_name[drvdata->engine], drvdata);
+       if (rc < 0)
+               return dev_err_probe(&pdev->dev, rc, "irq request failed\n");
+
+       i2c_parse_fw_timings(&pdev->dev, &drvdata->t, true);
+
+       gxp_i2c_init(drvdata);
+
+       /* Enable interrupt */
+       regmap_update_bits(i2cg_map, GXP_I2CINTEN, BIT(drvdata->engine),
+                          BIT(drvdata->engine));
+
+       adapter = &drvdata->adapter;
+       i2c_set_adapdata(adapter, drvdata);
+
+       adapter->owner = THIS_MODULE;
+       strscpy(adapter->name, "HPE GXP I2C adapter", sizeof(adapter->name));
+       adapter->algo = &gxp_i2c_algo;
+       adapter->dev.parent = &pdev->dev;
+       adapter->dev.of_node = pdev->dev.of_node;
+
+       rc = i2c_add_adapter(adapter);
+       if (rc)
+               return dev_err_probe(&pdev->dev, rc, "i2c add adapter failed\n");
+
+       return 0;
+}
+
+static int gxp_i2c_remove(struct platform_device *pdev)
+{
+       struct gxp_i2c_drvdata *drvdata = platform_get_drvdata(pdev);
+
+       /* Disable interrupt */
+       regmap_update_bits(i2cg_map, GXP_I2CINTEN, BIT(drvdata->engine), 0);
+       i2c_del_adapter(&drvdata->adapter);
+
+       return 0;
+}
+
+static const struct of_device_id gxp_i2c_of_match[] = {
+       { .compatible = "hpe,gxp-i2c" },
+       {},
+};
+MODULE_DEVICE_TABLE(of, gxp_i2c_of_match);
+
+static struct platform_driver gxp_i2c_driver = {
+       .probe  = gxp_i2c_probe,
+       .remove = gxp_i2c_remove,
+       .driver = {
+               .name = "gxp-i2c",
+               .of_match_table = gxp_i2c_of_match,
+       },
+};
+module_platform_driver(gxp_i2c_driver);
+
+MODULE_AUTHOR("Nick Hawkins <nick.hawkins@hpe.com>");
+MODULE_DESCRIPTION("HPE GXP I2C bus driver");
+MODULE_LICENSE("GPL");
index 1fda1eaa6d6ab0560ffbe2cfdca79cd7a7d887c6..ac5326747c5197630eb8b85ab3ca14ac907f17c7 100644 (file)
@@ -434,7 +434,7 @@ static int i801_wait_intr(struct i801_priv *priv)
                busy = status & SMBHSTSTS_HOST_BUSY;
                status &= STATUS_ERROR_FLAGS | SMBHSTSTS_INTR;
                if (!busy && status)
-                       return status;
+                       return status & STATUS_ERROR_FLAGS;
        } while (time_is_after_eq_jiffies(timeout));
 
        return -ETIMEDOUT;
@@ -458,26 +458,20 @@ static int i801_wait_byte_done(struct i801_priv *priv)
 
 static int i801_transaction(struct i801_priv *priv, int xact)
 {
-       int status;
        unsigned long result;
        const struct i2c_adapter *adap = &priv->adapter;
 
-       status = i801_check_pre(priv);
-       if (status < 0)
-               return status;
-
        if (priv->features & FEATURE_IRQ) {
                reinit_completion(&priv->done);
                outb_p(xact | SMBHSTCNT_INTREN | SMBHSTCNT_START,
                       SMBHSTCNT(priv));
                result = wait_for_completion_timeout(&priv->done, adap->timeout);
-               return i801_check_post(priv, result ? priv->status : -ETIMEDOUT);
+               return result ? priv->status : -ETIMEDOUT;
        }
 
        outb_p(xact | SMBHSTCNT_START, SMBHSTCNT(priv));
 
-       status = i801_wait_intr(priv);
-       return i801_check_post(priv, status);
+       return i801_wait_intr(priv);
 }
 
 static int i801_block_transaction_by_block(struct i801_priv *priv,
@@ -511,19 +505,23 @@ static int i801_block_transaction_by_block(struct i801_priv *priv,
 
        status = i801_transaction(priv, xact);
        if (status)
-               return status;
+               goto out;
 
        if (read_write == I2C_SMBUS_READ ||
            command == I2C_SMBUS_BLOCK_PROC_CALL) {
                len = inb_p(SMBHSTDAT0(priv));
-               if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
-                       return -EPROTO;
+               if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
+                       status = -EPROTO;
+                       goto out;
+               }
 
                data->block[0] = len;
                for (i = 0; i < len; i++)
                        data->block[i + 1] = inb_p(SMBBLKDAT(priv));
        }
-       return 0;
+out:
+       outb_p(inb_p(SMBAUXCTL(priv)) & ~SMBAUXCTL_E32B, SMBAUXCTL(priv));
+       return status;
 }
 
 static void i801_isr_byte_done(struct i801_priv *priv)
@@ -558,9 +556,6 @@ static void i801_isr_byte_done(struct i801_priv *priv)
                /* Write next byte, except for IRQ after last byte */
                outb_p(priv->data[++priv->count], SMBBLKDAT(priv));
        }
-
-       /* Clear BYTE_DONE to continue with next byte */
-       outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));
 }
 
 static irqreturn_t i801_host_notify_isr(struct i801_priv *priv)
@@ -590,7 +585,6 @@ static irqreturn_t i801_host_notify_isr(struct i801_priv *priv)
  *      BUS_ERR - SMI# transaction collision
  *      FAILED - transaction was canceled due to a KILL request
  *    When any of these occur, update ->status and signal completion.
- *    ->status must be cleared before kicking off the next transaction.
  *
  * 2) For byte-by-byte (I2C read/write) transactions, one BYTE_DONE interrupt
  *    occurs for each byte of a byte-by-byte to prepare the next byte.
@@ -615,25 +609,20 @@ static irqreturn_t i801_isr(int irq, void *dev_id)
        }
 
        status = inb_p(SMBHSTSTS(priv));
-       if (status & SMBHSTSTS_BYTE_DONE)
+       if ((status & (SMBHSTSTS_BYTE_DONE | STATUS_ERROR_FLAGS)) == SMBHSTSTS_BYTE_DONE)
                i801_isr_byte_done(priv);
 
        /*
-        * Clear remaining IRQ sources: Completion of last command, errors
-        * and the SMB_ALERT signal. SMB_ALERT status is set after signal
-        * assertion independently of the interrupt generation being blocked
-        * or not so clear it always when the status is set.
-        */
-       status &= SMBHSTSTS_INTR | STATUS_ERROR_FLAGS | SMBHSTSTS_SMBALERT_STS;
-       if (status)
-               outb_p(status, SMBHSTSTS(priv));
-       status &= ~SMBHSTSTS_SMBALERT_STS; /* SMB_ALERT not reported */
-       /*
-        * Report transaction result.
-        * ->status must be cleared before the next transaction is started.
+        * Clear IRQ sources: SMB_ALERT status is set after signal assertion
+        * independently of the interrupt generation being blocked or not
+        * so clear it always when the status is set.
         */
+       status &= STATUS_FLAGS | SMBHSTSTS_SMBALERT_STS;
+       outb_p(status, SMBHSTSTS(priv));
+
+       status &= STATUS_ERROR_FLAGS | SMBHSTSTS_INTR;
        if (status) {
-               priv->status = status;
+               priv->status = status & STATUS_ERROR_FLAGS;
                complete(&priv->done);
        }
 
@@ -658,10 +647,6 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
        if (command == I2C_SMBUS_BLOCK_PROC_CALL)
                return -EOPNOTSUPP;
 
-       status = i801_check_pre(priv);
-       if (status < 0)
-               return status;
-
        len = data->block[0];
 
        if (read_write == I2C_SMBUS_WRITE) {
@@ -687,7 +672,7 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
                reinit_completion(&priv->done);
                outb_p(priv->cmd | SMBHSTCNT_START, SMBHSTCNT(priv));
                result = wait_for_completion_timeout(&priv->done, adap->timeout);
-               return i801_check_post(priv, result ? priv->status : -ETIMEDOUT);
+               return result ? priv->status : -ETIMEDOUT;
        }
 
        for (i = 1; i <= len; i++) {
@@ -701,7 +686,7 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
 
                status = i801_wait_byte_done(priv);
                if (status)
-                       goto exit;
+                       return status;
 
                if (i == 1 && read_write == I2C_SMBUS_READ
                 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
@@ -731,14 +716,82 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
                outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));
        }
 
-       status = i801_wait_intr(priv);
-exit:
-       return i801_check_post(priv, status);
+       return i801_wait_intr(priv);
+}
+
+static void i801_set_hstadd(struct i801_priv *priv, u8 addr, char read_write)
+{
+       outb_p((addr << 1) | (read_write & 0x01), SMBHSTADD(priv));
+}
+
+/* Single value transaction function */
+static int i801_simple_transaction(struct i801_priv *priv, union i2c_smbus_data *data,
+                                  u8 addr, u8 hstcmd, char read_write, int command)
+{
+       int xact, ret;
+
+       switch (command) {
+       case I2C_SMBUS_QUICK:
+               i801_set_hstadd(priv, addr, read_write);
+               xact = I801_QUICK;
+               break;
+       case I2C_SMBUS_BYTE:
+               i801_set_hstadd(priv, addr, read_write);
+               if (read_write == I2C_SMBUS_WRITE)
+                       outb_p(hstcmd, SMBHSTCMD(priv));
+               xact = I801_BYTE;
+               break;
+       case I2C_SMBUS_BYTE_DATA:
+               i801_set_hstadd(priv, addr, read_write);
+               if (read_write == I2C_SMBUS_WRITE)
+                       outb_p(data->byte, SMBHSTDAT0(priv));
+               outb_p(hstcmd, SMBHSTCMD(priv));
+               xact = I801_BYTE_DATA;
+               break;
+       case I2C_SMBUS_WORD_DATA:
+               i801_set_hstadd(priv, addr, read_write);
+               if (read_write == I2C_SMBUS_WRITE) {
+                       outb_p(data->word & 0xff, SMBHSTDAT0(priv));
+                       outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv));
+               }
+               outb_p(hstcmd, SMBHSTCMD(priv));
+               xact = I801_WORD_DATA;
+               break;
+       case I2C_SMBUS_PROC_CALL:
+               i801_set_hstadd(priv, addr, I2C_SMBUS_WRITE);
+               outb_p(data->word & 0xff, SMBHSTDAT0(priv));
+               outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv));
+               outb_p(hstcmd, SMBHSTCMD(priv));
+               read_write = I2C_SMBUS_READ;
+               xact = I801_PROC_CALL;
+               break;
+       default:
+               pci_err(priv->pci_dev, "Unsupported transaction %d\n", command);
+               return -EOPNOTSUPP;
+       }
+
+       ret = i801_transaction(priv, xact);
+       if (ret || read_write == I2C_SMBUS_WRITE)
+               return ret;
+
+       switch (command) {
+       case I2C_SMBUS_BYTE:
+       case I2C_SMBUS_BYTE_DATA:
+               data->byte = inb_p(SMBHSTDAT0(priv));
+               break;
+       case I2C_SMBUS_WORD_DATA:
+       case I2C_SMBUS_PROC_CALL:
+               data->word = inb_p(SMBHSTDAT0(priv)) +
+                            (inb_p(SMBHSTDAT1(priv)) << 8);
+               break;
+       }
+
+       return 0;
 }
 
 /* Block transaction function */
 static int i801_block_transaction(struct i801_priv *priv, union i2c_smbus_data *data,
-                                 char read_write, int command)
+                                 u8 addr, u8 hstcmd, char read_write, int command)
 {
        int result = 0;
        unsigned char hostc;
@@ -748,7 +801,29 @@ static int i801_block_transaction(struct i801_priv *priv, union i2c_smbus_data *
        else if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
                return -EPROTO;
 
-       if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
+       switch (command) {
+       case I2C_SMBUS_BLOCK_DATA:
+               i801_set_hstadd(priv, addr, read_write);
+               outb_p(hstcmd, SMBHSTCMD(priv));
+               break;
+       case I2C_SMBUS_I2C_BLOCK_DATA:
+               /*
+                * NB: page 240 of ICH5 datasheet shows that the R/#W
+                * bit should be cleared here, even when reading.
+                * However if SPD Write Disable is set (Lynx Point and later),
+                * the read will fail if we don't set the R/#W bit.
+                */
+               i801_set_hstadd(priv, addr,
+                               priv->original_hstcfg & SMBHSTCFG_SPD_WD ?
+                               read_write : I2C_SMBUS_WRITE);
+               if (read_write == I2C_SMBUS_READ) {
+                       /* NB: page 240 of ICH5 datasheet also shows
+                        * that DATA1 is the cmd field when reading
+                        */
+                       outb_p(hstcmd, SMBHSTDAT1(priv));
+               } else
+                       outb_p(hstcmd, SMBHSTCMD(priv));
+
                if (read_write == I2C_SMBUS_WRITE) {
                        /* set I2C_EN bit in configuration register */
                        pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc);
@@ -759,6 +834,12 @@ static int i801_block_transaction(struct i801_priv *priv, union i2c_smbus_data *
                                "I2C block read is unsupported!\n");
                        return -EOPNOTSUPP;
                }
+               break;
+       case I2C_SMBUS_BLOCK_PROC_CALL:
+               /* Needs to be flagged as write transaction */
+               i801_set_hstadd(priv, addr, I2C_SMBUS_WRITE);
+               outb_p(hstcmd, SMBHSTCMD(priv));
+               break;
        }
 
        /* Experience has shown that the block buffer can only be used for
@@ -787,9 +868,7 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
                       unsigned short flags, char read_write, u8 command,
                       int size, union i2c_smbus_data *data)
 {
-       int hwpec;
-       int block = 0;
-       int ret, xact;
+       int hwpec, ret;
        struct i801_priv *priv = i2c_get_adapdata(adap);
 
        mutex_lock(&priv->acpi_lock);
@@ -800,127 +879,34 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
 
        pm_runtime_get_sync(&priv->pci_dev->dev);
 
+       ret = i801_check_pre(priv);
+       if (ret)
+               goto out;
+
        hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
                && size != I2C_SMBUS_QUICK
                && size != I2C_SMBUS_I2C_BLOCK_DATA;
 
-       switch (size) {
-       case I2C_SMBUS_QUICK:
-               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
-                      SMBHSTADD(priv));
-               xact = I801_QUICK;
-               break;
-       case I2C_SMBUS_BYTE:
-               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
-                      SMBHSTADD(priv));
-               if (read_write == I2C_SMBUS_WRITE)
-                       outb_p(command, SMBHSTCMD(priv));
-               xact = I801_BYTE;
-               break;
-       case I2C_SMBUS_BYTE_DATA:
-               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
-                      SMBHSTADD(priv));
-               outb_p(command, SMBHSTCMD(priv));
-               if (read_write == I2C_SMBUS_WRITE)
-                       outb_p(data->byte, SMBHSTDAT0(priv));
-               xact = I801_BYTE_DATA;
-               break;
-       case I2C_SMBUS_WORD_DATA:
-               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
-                      SMBHSTADD(priv));
-               outb_p(command, SMBHSTCMD(priv));
-               if (read_write == I2C_SMBUS_WRITE) {
-                       outb_p(data->word & 0xff, SMBHSTDAT0(priv));
-                       outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv));
-               }
-               xact = I801_WORD_DATA;
-               break;
-       case I2C_SMBUS_PROC_CALL:
-               outb_p((addr & 0x7f) << 1, SMBHSTADD(priv));
-               outb_p(command, SMBHSTCMD(priv));
-               outb_p(data->word & 0xff, SMBHSTDAT0(priv));
-               outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv));
-               xact = I801_PROC_CALL;
-               read_write = I2C_SMBUS_READ;
-               break;
-       case I2C_SMBUS_BLOCK_DATA:
-               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
-                      SMBHSTADD(priv));
-               outb_p(command, SMBHSTCMD(priv));
-               block = 1;
-               break;
-       case I2C_SMBUS_I2C_BLOCK_DATA:
-               /*
-                * NB: page 240 of ICH5 datasheet shows that the R/#W
-                * bit should be cleared here, even when reading.
-                * However if SPD Write Disable is set (Lynx Point and later),
-                * the read will fail if we don't set the R/#W bit.
-                */
-               outb_p(((addr & 0x7f) << 1) |
-                      ((priv->original_hstcfg & SMBHSTCFG_SPD_WD) ?
-                       (read_write & 0x01) : 0),
-                      SMBHSTADD(priv));
-               if (read_write == I2C_SMBUS_READ) {
-                       /* NB: page 240 of ICH5 datasheet also shows
-                        * that DATA1 is the cmd field when reading */
-                       outb_p(command, SMBHSTDAT1(priv));
-               } else
-                       outb_p(command, SMBHSTCMD(priv));
-               block = 1;
-               break;
-       case I2C_SMBUS_BLOCK_PROC_CALL:
-               /*
-                * Bit 0 of the slave address register always indicate a write
-                * command.
-                */
-               outb_p((addr & 0x7f) << 1, SMBHSTADD(priv));
-               outb_p(command, SMBHSTCMD(priv));
-               block = 1;
-               break;
-       default:
-               dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n",
-                       size);
-               ret = -EOPNOTSUPP;
-               goto out;
-       }
-
        if (hwpec)      /* enable/disable hardware PEC */
                outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv));
        else
                outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC),
                       SMBAUXCTL(priv));
 
-       if (block)
-               ret = i801_block_transaction(priv, data, read_write, size);
+       if (size == I2C_SMBUS_BLOCK_DATA ||
+           size == I2C_SMBUS_I2C_BLOCK_DATA ||
+           size == I2C_SMBUS_BLOCK_PROC_CALL)
+               ret = i801_block_transaction(priv, data, addr, command, read_write, size);
        else
-               ret = i801_transaction(priv, xact);
-
-       /* Some BIOSes don't like it when PEC is enabled at reboot or resume
-          time, so we forcibly disable it after every transaction. Turn off
-          E32B for the same reason. */
-       if (hwpec || block)
-               outb_p(inb_p(SMBAUXCTL(priv)) &
-                      ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
-
-       if (block)
-               goto out;
-       if (ret)
-               goto out;
-       if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
-               goto out;
+               ret = i801_simple_transaction(priv, data, addr, command, read_write, size);
 
-       switch (xact) {
-       case I801_BYTE: /* Result put in SMBHSTDAT0 */
-       case I801_BYTE_DATA:
-               data->byte = inb_p(SMBHSTDAT0(priv));
-               break;
-       case I801_WORD_DATA:
-       case I801_PROC_CALL:
-               data->word = inb_p(SMBHSTDAT0(priv)) +
-                            (inb_p(SMBHSTDAT1(priv)) << 8);
-               break;
-       }
+       ret = i801_check_post(priv, ret);
 
+       /* Some BIOSes don't like it when PEC is enabled at reboot or resume
+        * time, so we forcibly disable it after every transaction.
+        */
+       if (hwpec)
+               outb_p(inb_p(SMBAUXCTL(priv)) & ~SMBAUXCTL_CRC, SMBAUXCTL(priv));
 out:
        /*
         * Unlock the SMBus device for use by BIOS/ACPI,
@@ -1667,6 +1653,10 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
        }
        priv->features &= ~disable_features;
 
+       /* The block process call uses block buffer mode */
+       if (!(priv->features & FEATURE_BLOCK_BUFFER))
+               priv->features &= ~FEATURE_BLOCK_PROC;
+
        err = pcim_enable_device(dev);
        if (err) {
                dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
@@ -1714,11 +1704,6 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
                outb_p(inb_p(SMBAUXCTL(priv)) &
                       ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
 
-       /* Remember original Interrupt and Host Notify settings */
-       priv->original_hstcnt = inb_p(SMBHSTCNT(priv)) & ~SMBHSTCNT_KILL;
-       if (priv->features & FEATURE_HOST_NOTIFY)
-               priv->original_slvcmd = inb_p(SMBSLVCMD(priv));
-
        /* Default timeout in interrupt mode: 200 ms */
        priv->adapter.timeout = HZ / 5;
 
@@ -1748,6 +1733,15 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
        dev_info(&dev->dev, "SMBus using %s\n",
                 priv->features & FEATURE_IRQ ? "PCI interrupt" : "polling");
 
+       /* Host notification uses an interrupt */
+       if (!(priv->features & FEATURE_IRQ))
+               priv->features &= ~FEATURE_HOST_NOTIFY;
+
+       /* Remember original Interrupt and Host Notify settings */
+       priv->original_hstcnt = inb_p(SMBHSTCNT(priv)) & ~SMBHSTCNT_KILL;
+       if (priv->features & FEATURE_HOST_NOTIFY)
+               priv->original_slvcmd = inb_p(SMBSLVCMD(priv));
+
        i801_add_tco(priv);
 
        snprintf(priv->adapter.name, sizeof(priv->adapter.name),
diff --git a/drivers/i2c/busses/i2c-ls2x.c b/drivers/i2c/busses/i2c-ls2x.c
new file mode 100644 (file)
index 0000000..ebae603
--- /dev/null
@@ -0,0 +1,370 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Loongson-2K/Loongson LS7A I2C master mode driver
+ *
+ * Copyright (C) 2013 Loongson Technology Corporation Limited.
+ * Copyright (C) 2014-2017 Lemote, Inc.
+ * Copyright (C) 2018-2022 Loongson Technology Corporation Limited.
+ *
+ * Originally written by liushaozong
+ * Rewritten for mainline by Binbin Zhou <zhoubinbin@loongson.cn>
+ */
+
+#include <linux/bits.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/iopoll.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/units.h>
+
+/* I2C Registers */
+#define I2C_LS2X_PRER          0x0 /* Freq Division Register(16 bits) */
+#define I2C_LS2X_CTR           0x2 /* Control Register */
+#define I2C_LS2X_TXR           0x3 /* Transport Data Register */
+#define I2C_LS2X_RXR           0x3 /* Receive Data Register */
+#define I2C_LS2X_CR            0x4 /* Command Control Register */
+#define I2C_LS2X_SR            0x4 /* State Register */
+
+/* Command Control Register Bit */
+#define LS2X_CR_START          BIT(7) /* Start signal */
+#define LS2X_CR_STOP           BIT(6) /* Stop signal */
+#define LS2X_CR_READ           BIT(5) /* Read signal */
+#define LS2X_CR_WRITE          BIT(4) /* Write signal */
+#define LS2X_CR_ACK            BIT(3) /* Response signal */
+#define LS2X_CR_IACK           BIT(0) /* Interrupt response signal */
+
+/* State Register Bit */
+#define LS2X_SR_NOACK          BIT(7) /* Receive NACK */
+#define LS2X_SR_BUSY           BIT(6) /* Bus busy state */
+#define LS2X_SR_AL             BIT(5) /* Arbitration lost */
+#define LS2X_SR_TIP            BIT(1) /* Transmission state */
+#define LS2X_SR_IF             BIT(0) /* Interrupt flag */
+
+/* Control Register Bit */
+#define LS2X_CTR_EN            BIT(7) /* 0: I2c frequency setting 1: Normal */
+#define LS2X_CTR_IEN           BIT(6) /* Enable i2c interrupt */
+#define LS2X_CTR_MST           BIT(5) /* 0: Slave mode 1: Master mode */
+#define CTR_FREQ_MASK          GENMASK(7, 6)
+#define CTR_READY_MASK         GENMASK(7, 5)
+
+/* The PCLK frequency from LPB */
+#define LS2X_I2C_PCLK_FREQ     (50 * HZ_PER_MHZ)
+
+/* The default bus frequency, which is an empirical value */
+#define LS2X_I2C_FREQ_STD      (33 * HZ_PER_KHZ)
+
+struct ls2x_i2c_priv {
+       struct i2c_adapter      adapter;
+       void __iomem            *base;
+       struct i2c_timings      i2c_t;
+       struct completion       cmd_complete;
+};
+
+/*
+ * Interrupt service routine.
+ * This gets called whenever an I2C interrupt occurs.
+ */
+static irqreturn_t ls2x_i2c_isr(int this_irq, void *dev_id)
+{
+       struct ls2x_i2c_priv *priv = dev_id;
+
+       if (!(readb(priv->base + I2C_LS2X_SR) & LS2X_SR_IF))
+               return IRQ_NONE;
+
+       writeb(LS2X_CR_IACK, priv->base + I2C_LS2X_CR);
+       complete(&priv->cmd_complete);
+       return IRQ_HANDLED;
+}
+
+/*
+ * The ls2x i2c controller supports standard mode and fast mode, so the
+ * maximum bus frequency is '400kHz'.
+ * The bus frequency is set to the empirical value of '33KHz' by default,
+ * but it can also be taken from ACPI or FDT for compatibility with more
+ * devices.
+ */
+static void ls2x_i2c_adjust_bus_speed(struct ls2x_i2c_priv *priv)
+{
+       struct i2c_timings *t = &priv->i2c_t;
+       struct device *dev = priv->adapter.dev.parent;
+       u32 acpi_speed = i2c_acpi_find_bus_speed(dev);
+
+       i2c_parse_fw_timings(dev, t, false);
+
+       if (acpi_speed || t->bus_freq_hz)
+               t->bus_freq_hz = max(t->bus_freq_hz, acpi_speed);
+       else
+               t->bus_freq_hz = LS2X_I2C_FREQ_STD;
+
+       /* Calculate and set i2c frequency. */
+       writew(LS2X_I2C_PCLK_FREQ / (5 * t->bus_freq_hz) - 1,
+              priv->base + I2C_LS2X_PRER);
+}
+
+static void ls2x_i2c_init(struct ls2x_i2c_priv *priv)
+{
+       /* Set i2c frequency setting mode and disable interrupts. */
+       writeb(readb(priv->base + I2C_LS2X_CTR) & ~CTR_FREQ_MASK,
+              priv->base + I2C_LS2X_CTR);
+
+       ls2x_i2c_adjust_bus_speed(priv);
+
+       /* Set i2c normal operating mode and enable interrupts. */
+       writeb(readb(priv->base + I2C_LS2X_CTR) | CTR_READY_MASK,
+              priv->base + I2C_LS2X_CTR);
+}
+
+static int ls2x_i2c_xfer_byte(struct ls2x_i2c_priv *priv, u8 txdata, u8 *rxdatap)
+{
+       u8 rxdata;
+       unsigned long time_left;
+
+       writeb(txdata, priv->base + I2C_LS2X_CR);
+
+       time_left = wait_for_completion_timeout(&priv->cmd_complete,
+                                               priv->adapter.timeout);
+       if (!time_left)
+               return -ETIMEDOUT;
+
+       rxdata = readb(priv->base + I2C_LS2X_SR);
+       if (rxdatap)
+               *rxdatap = rxdata;
+
+       return 0;
+}
+
+static int ls2x_i2c_send_byte(struct ls2x_i2c_priv *priv, u8 txdata)
+{
+       int ret;
+       u8 rxdata;
+
+       ret = ls2x_i2c_xfer_byte(priv, txdata, &rxdata);
+       if (ret)
+               return ret;
+
+       if (rxdata & LS2X_SR_AL)
+               return -EAGAIN;
+
+       if (rxdata & LS2X_SR_NOACK)
+               return -ENXIO;
+
+       return 0;
+}
+
+static int ls2x_i2c_stop(struct ls2x_i2c_priv *priv)
+{
+       u8 value;
+
+       writeb(LS2X_CR_STOP, priv->base + I2C_LS2X_CR);
+       return readb_poll_timeout(priv->base + I2C_LS2X_SR, value,
+                                 !(value & LS2X_SR_BUSY), 100,
+                                 jiffies_to_usecs(priv->adapter.timeout));
+}
+
+static int ls2x_i2c_start(struct ls2x_i2c_priv *priv, struct i2c_msg *msgs)
+{
+       reinit_completion(&priv->cmd_complete);
+
+       writeb(i2c_8bit_addr_from_msg(msgs), priv->base + I2C_LS2X_TXR);
+       return ls2x_i2c_send_byte(priv, LS2X_CR_START | LS2X_CR_WRITE);
+}
+
+static int ls2x_i2c_rx(struct ls2x_i2c_priv *priv, struct i2c_msg *msg)
+{
+       int ret;
+       u8 rxdata, *buf = msg->buf;
+       u16 len = msg->len;
+
+       /* Contains steps to send start condition and address. */
+       ret = ls2x_i2c_start(priv, msg);
+       if (ret)
+               return ret;
+
+       while (len--) {
+               ret = ls2x_i2c_xfer_byte(priv,
+                                        LS2X_CR_READ | (len ? 0 : LS2X_CR_ACK),
+                                        &rxdata);
+               if (ret)
+                       return ret;
+
+               *buf++ = readb(priv->base + I2C_LS2X_RXR);
+       }
+
+       return 0;
+}
+
+static int ls2x_i2c_tx(struct ls2x_i2c_priv *priv, struct i2c_msg *msg)
+{
+       int ret;
+       u8 *buf = msg->buf;
+       u16 len = msg->len;
+
+       /* Contains steps to send start condition and address. */
+       ret = ls2x_i2c_start(priv, msg);
+       if (ret)
+               return ret;
+
+       while (len--) {
+               writeb(*buf++, priv->base + I2C_LS2X_TXR);
+
+               ret = ls2x_i2c_send_byte(priv, LS2X_CR_WRITE);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int ls2x_i2c_xfer_one(struct ls2x_i2c_priv *priv,
+                            struct i2c_msg *msg, bool stop)
+{
+       int ret;
+
+       if (msg->flags & I2C_M_RD)
+               ret = ls2x_i2c_rx(priv, msg);
+       else
+               ret = ls2x_i2c_tx(priv, msg);
+
+       if (ret < 0) {
+               /* Fatel error. Needs reinit. */
+               if (ret == -ETIMEDOUT)
+                       ls2x_i2c_init(priv);
+
+               return ret;
+       }
+
+       if (stop) {
+               /* Failed to issue STOP. Needs reinit. */
+               ret = ls2x_i2c_stop(priv);
+               if (ret)
+                       ls2x_i2c_init(priv);
+       }
+
+       return ret;
+}
+
+static int ls2x_i2c_master_xfer(struct i2c_adapter *adap,
+                               struct i2c_msg *msgs, int num)
+{
+       int ret;
+       struct i2c_msg *msg, *emsg = msgs + num;
+       struct ls2x_i2c_priv *priv = i2c_get_adapdata(adap);
+
+       for (msg = msgs; msg < emsg; msg++) {
+               ret = ls2x_i2c_xfer_one(priv, msg, msg == emsg - 1);
+               if (ret)
+                       return ret;
+       }
+
+       return num;
+}
+
+static unsigned int ls2x_i2c_func(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm ls2x_i2c_algo = {
+       .master_xfer    = ls2x_i2c_master_xfer,
+       .functionality  = ls2x_i2c_func,
+};
+
+static int ls2x_i2c_probe(struct platform_device *pdev)
+{
+       int ret, irq;
+       struct i2c_adapter *adap;
+       struct ls2x_i2c_priv *priv;
+       struct device *dev = &pdev->dev;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       /* Map hardware registers */
+       priv->base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(priv->base))
+               return PTR_ERR(priv->base);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
+
+       /* Add the i2c adapter */
+       adap = &priv->adapter;
+       adap->retries = 5;
+       adap->nr = pdev->id;
+       adap->dev.parent = dev;
+       adap->owner = THIS_MODULE;
+       adap->algo = &ls2x_i2c_algo;
+       adap->timeout = msecs_to_jiffies(100);
+       device_set_node(&adap->dev, dev_fwnode(dev));
+       i2c_set_adapdata(adap, priv);
+       strscpy(adap->name, pdev->name, sizeof(adap->name));
+       init_completion(&priv->cmd_complete);
+       platform_set_drvdata(pdev, priv);
+
+       ls2x_i2c_init(priv);
+
+       ret = devm_request_irq(dev, irq, ls2x_i2c_isr, IRQF_SHARED, "ls2x-i2c",
+                              priv);
+       if (ret < 0)
+               return dev_err_probe(dev, ret, "Unable to request irq %d\n", irq);
+
+       return devm_i2c_add_adapter(dev, adap);
+}
+
+static int ls2x_i2c_suspend(struct device *dev)
+{
+       struct ls2x_i2c_priv *priv = dev_get_drvdata(dev);
+
+       /* Disable interrupts */
+       writeb(readb(priv->base + I2C_LS2X_CTR) & ~LS2X_CTR_IEN,
+              priv->base + I2C_LS2X_CTR);
+
+       return 0;
+}
+
+static int ls2x_i2c_resume(struct device *dev)
+{
+       ls2x_i2c_init(dev_get_drvdata(dev));
+       return 0;
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(ls2x_i2c_pm_ops,
+                                ls2x_i2c_suspend, ls2x_i2c_resume, NULL);
+
+static const struct of_device_id ls2x_i2c_id_table[] = {
+       { .compatible = "loongson,ls2k-i2c" },
+       { .compatible = "loongson,ls7a-i2c" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ls2x_i2c_id_table);
+
+static const struct acpi_device_id ls2x_i2c_acpi_match[] = {
+       { "LOON0004" }, /* Loongson LS7A */
+       { }
+};
+MODULE_DEVICE_TABLE(acpi, ls2x_i2c_acpi_match);
+
+static struct platform_driver ls2x_i2c_driver = {
+       .probe          = ls2x_i2c_probe,
+       .driver         = {
+               .name   = "ls2x-i2c",
+               .pm     = pm_sleep_ptr(&ls2x_i2c_pm_ops),
+               .of_match_table = ls2x_i2c_id_table,
+               .acpi_match_table = ls2x_i2c_acpi_match,
+       },
+};
+module_platform_driver(ls2x_i2c_driver);
+
+MODULE_DESCRIPTION("Loongson LS2X I2C Bus driver");
+MODULE_AUTHOR("Loongson Technology Corporation Limited");
+MODULE_LICENSE("GPL");
index d80e59340d97a1e6f7790880b4f937e05cf5650e..43dd966d5ef58556284d211669417896a8d27f23 100644 (file)
@@ -1366,20 +1366,17 @@ static int mtk_i2c_probe(struct platform_device *pdev)
 {
        int ret = 0;
        struct mtk_i2c *i2c;
-       struct resource *res;
        int i, irq, speed_clk;
 
        i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
        if (!i2c)
                return -ENOMEM;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       i2c->base = devm_ioremap_resource(&pdev->dev, res);
+       i2c->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
        if (IS_ERR(i2c->base))
                return PTR_ERR(i2c->base);
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       i2c->pdmabase = devm_ioremap_resource(&pdev->dev, res);
+       i2c->pdmabase = devm_platform_get_and_ioremap_resource(pdev, 1, NULL);
        if (IS_ERR(i2c->pdmabase))
                return PTR_ERR(i2c->pdmabase);
 
index a4b97fe3c3a5bc743e0bbe45846af25a86aff552..01358472680c4cd905217ee257225874fdf65873 100644 (file)
@@ -811,9 +811,15 @@ static const struct cci_data cci_v2_data = {
 
 static const struct of_device_id cci_dt_match[] = {
        { .compatible = "qcom,msm8226-cci", .data = &cci_v1_data},
-       { .compatible = "qcom,msm8916-cci", .data = &cci_v1_data},
        { .compatible = "qcom,msm8974-cci", .data = &cci_v1_5_data},
        { .compatible = "qcom,msm8996-cci", .data = &cci_v2_data},
+
+
+       /*
+        * Legacy compatibles kept for backwards compatibility.
+        * Do not add any new ones unless they introduce a new config
+        */
+       { .compatible = "qcom,msm8916-cci", .data = &cci_v1_data},
        { .compatible = "qcom,sdm845-cci", .data = &cci_v2_data},
        { .compatible = "qcom,sm8250-cci", .data = &cci_v2_data},
        { .compatible = "qcom,sm8450-cci", .data = &cci_v2_data},
index 80d586b0be7a1e37f17a6754c8cb689cbe57f19c..83909b02a03ee063b1d82358bc261a7a51f78a31 100644 (file)
@@ -1025,7 +1025,7 @@ static const struct dev_pm_ops geni_i2c_pm_ops = {
                                                                        NULL)
 };
 
-const struct geni_i2c_desc i2c_master_hub = {
+static const struct geni_i2c_desc i2c_master_hub = {
        .has_core_clk = true,
        .icc_ddr = NULL,
        .no_dma_support = true,
index 88482316d22a050a982a8024f046cf02d7378393..f823913b75a6fc60250d42e6e973a552fe995e8b 100644 (file)
@@ -740,7 +740,6 @@ static int st_i2c_xfer(struct i2c_adapter *i2c_adap,
        return (ret < 0) ? ret : i;
 }
 
-#ifdef CONFIG_PM_SLEEP
 static int st_i2c_suspend(struct device *dev)
 {
        struct st_i2c_dev *i2c_dev = dev_get_drvdata(dev);
@@ -762,11 +761,7 @@ static int st_i2c_resume(struct device *dev)
        return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(st_i2c_pm, st_i2c_suspend, st_i2c_resume);
-#define ST_I2C_PM      (&st_i2c_pm)
-#else
-#define ST_I2C_PM      NULL
-#endif
+static DEFINE_SIMPLE_DEV_PM_OPS(st_i2c_pm, st_i2c_suspend, st_i2c_resume);
 
 static u32 st_i2c_func(struct i2c_adapter *adap)
 {
@@ -901,7 +896,7 @@ static struct platform_driver st_i2c_driver = {
        .driver = {
                .name = "st-i2c",
                .of_match_table = st_i2c_match,
-               .pm = ST_I2C_PM,
+               .pm = pm_sleep_ptr(&st_i2c_pm),
        },
        .probe = st_i2c_probe,
        .remove = st_i2c_remove,
index bee5a2ef1f229d280d2e55d67267604145f030c6..dbb792fc197ec88bd72d5de315f87aceab3c321a 100644 (file)
@@ -32,6 +32,8 @@
 #include <linux/pm_runtime.h>
 
 #define DRIVER_NAME "xiic-i2c"
+#define DYNAMIC_MODE_READ_BROKEN_BIT   BIT(0)
+#define SMBUS_BLOCK_READ_MIN_LEN       3
 
 enum xilinx_i2c_state {
        STATE_DONE,
@@ -44,6 +46,12 @@ enum xiic_endian {
        BIG
 };
 
+enum i2c_scl_freq {
+       REG_VALUES_100KHZ = 0,
+       REG_VALUES_400KHZ = 1,
+       REG_VALUES_1MHZ = 2
+};
+
 /**
  * struct xiic_i2c - Internal representation of the XIIC I2C bus
  * @dev: Pointer to device structure
@@ -60,6 +68,12 @@ enum xiic_endian {
  * @clk: Pointer to AXI4-lite input clock
  * @state: See STATE_
  * @singlemaster: Indicates bus is single master
+ * @dynamic: Mode of controller
+ * @prev_msg_tx: Previous message is Tx
+ * @quirks: To hold platform specific bug info
+ * @smbus_block_read: Flag to handle block read
+ * @input_clk: Input clock to I2C controller
+ * @i2c_clk: I2C SCL frequency
  */
 struct xiic_i2c {
        struct device *dev;
@@ -76,6 +90,39 @@ struct xiic_i2c {
        struct clk *clk;
        enum xilinx_i2c_state state;
        bool singlemaster;
+       bool dynamic;
+       bool prev_msg_tx;
+       u32 quirks;
+       bool smbus_block_read;
+       unsigned long input_clk;
+       unsigned int i2c_clk;
+};
+
+struct xiic_version_data {
+       u32 quirks;
+};
+
+/**
+ * struct timing_regs - AXI I2C timing registers that depend on I2C spec
+ * @tsusta: setup time for a repeated START condition
+ * @tsusto: setup time for a STOP condition
+ * @thdsta: hold time for a repeated START condition
+ * @tsudat: setup time for data
+ * @tbuf: bus free time between STOP and START
+ */
+struct timing_regs {
+       unsigned int tsusta;
+       unsigned int tsusto;
+       unsigned int thdsta;
+       unsigned int tsudat;
+       unsigned int tbuf;
+};
+
+/* Reg values in ns derived from I2C spec and AXI I2C PG for different frequencies */
+static const struct timing_regs timing_reg_values[] = {
+       { 5700, 5000, 4300, 550, 5000 }, /* Reg values for 100KHz */
+       { 900, 900, 900, 400, 1600 },    /* Reg values for 400KHz */
+       { 380, 380, 380, 170, 620 },     /* Reg values for 1MHz   */
 };
 
 #define XIIC_MSB_OFFSET 0
@@ -96,6 +143,19 @@ struct xiic_i2c {
 #define XIIC_RFD_REG_OFFSET  (0x20 + XIIC_REG_OFFSET)  /* Rx FIFO Depth reg  */
 #define XIIC_GPO_REG_OFFSET  (0x24 + XIIC_REG_OFFSET)  /* Output Register    */
 
+/*
+ * Timing register offsets from RegisterBase. These are used only for
+ * setting i2c clock frequency for the line.
+ */
+#define XIIC_TSUSTA_REG_OFFSET (0x28 + XIIC_REG_OFFSET) /* TSUSTA Register */
+#define XIIC_TSUSTO_REG_OFFSET (0x2C + XIIC_REG_OFFSET) /* TSUSTO Register */
+#define XIIC_THDSTA_REG_OFFSET (0x30 + XIIC_REG_OFFSET) /* THDSTA Register */
+#define XIIC_TSUDAT_REG_OFFSET (0x34 + XIIC_REG_OFFSET) /* TSUDAT Register */
+#define XIIC_TBUF_REG_OFFSET   (0x38 + XIIC_REG_OFFSET) /* TBUF Register */
+#define XIIC_THIGH_REG_OFFSET  (0x3C + XIIC_REG_OFFSET) /* THIGH Register */
+#define XIIC_TLOW_REG_OFFSET   (0x40 + XIIC_REG_OFFSET) /* TLOW Register */
+#define XIIC_THDDAT_REG_OFFSET (0x44 + XIIC_REG_OFFSET) /* THDDAT Register */
+
 /* Control Register masks */
 #define XIIC_CR_ENABLE_DEVICE_MASK        0x01 /* Device enable = 1      */
 #define XIIC_CR_TX_FIFO_RESET_MASK        0x02 /* Transmit FIFO reset=1  */
@@ -143,6 +203,9 @@ struct xiic_i2c {
 #define XIIC_TX_DYN_START_MASK            0x0100 /* 1 = Set dynamic start */
 #define XIIC_TX_DYN_STOP_MASK             0x0200 /* 1 = Set dynamic stop */
 
+/* Dynamic mode constants */
+#define MAX_READ_LENGTH_DYNAMIC                255 /* Max length for dynamic read */
+
 /*
  * The following constants define the register offsets for the Interrupt
  * registers. There are some holes in the memory map for reserved addresses
@@ -275,12 +338,120 @@ static int xiic_clear_rx_fifo(struct xiic_i2c *i2c)
        return 0;
 }
 
+static int xiic_wait_tx_empty(struct xiic_i2c *i2c)
+{
+       u8 isr;
+       unsigned long timeout;
+
+       timeout = jiffies + XIIC_I2C_TIMEOUT;
+       for (isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET);
+               !(isr & XIIC_INTR_TX_EMPTY_MASK);
+                       isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET)) {
+               if (time_after(jiffies, timeout)) {
+                       dev_err(i2c->dev, "Timeout waiting at Tx empty\n");
+                       return -ETIMEDOUT;
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * xiic_setclk - Sets the configured clock rate
+ * @i2c: Pointer to the xiic device structure
+ *
+ * The timing register values are calculated according to the input clock
+ * frequency and configured scl frequency. For details, please refer the
+ * AXI I2C PG and NXP I2C Spec.
+ * Supported frequencies are 100KHz, 400KHz and 1MHz.
+ *
+ * Return: 0 on success (Supported frequency selected or not configurable in SW)
+ *        -EINVAL on failure (scl frequency not supported or THIGH is 0)
+ */
+static int xiic_setclk(struct xiic_i2c *i2c)
+{
+       unsigned int clk_in_mhz;
+       unsigned int index = 0;
+       u32 reg_val;
+
+       dev_dbg(i2c->adap.dev.parent,
+               "%s entry, i2c->input_clk: %ld, i2c->i2c_clk: %d\n",
+               __func__, i2c->input_clk, i2c->i2c_clk);
+
+       /* If not specified in DT, do not configure in SW. Rely only on Vivado design */
+       if (!i2c->i2c_clk || !i2c->input_clk)
+               return 0;
+
+       clk_in_mhz = DIV_ROUND_UP(i2c->input_clk, 1000000);
+
+       switch (i2c->i2c_clk) {
+       case I2C_MAX_FAST_MODE_PLUS_FREQ:
+               index = REG_VALUES_1MHZ;
+               break;
+       case I2C_MAX_FAST_MODE_FREQ:
+               index = REG_VALUES_400KHZ;
+               break;
+       case I2C_MAX_STANDARD_MODE_FREQ:
+               index = REG_VALUES_100KHZ;
+               break;
+       default:
+               dev_warn(i2c->adap.dev.parent, "Unsupported scl frequency\n");
+               return -EINVAL;
+       }
+
+       /*
+        * Value to be stored in a register is the number of clock cycles required
+        * for the time duration. So the time is divided by the input clock time
+        * period to get the number of clock cycles required. Refer Xilinx AXI I2C
+        * PG document and I2C specification for further details.
+        */
+
+       /* THIGH - Depends on SCL clock frequency(i2c_clk) as below */
+       reg_val = (DIV_ROUND_UP(i2c->input_clk, 2 * i2c->i2c_clk)) - 7;
+       if (reg_val == 0)
+               return -EINVAL;
+
+       xiic_setreg32(i2c, XIIC_THIGH_REG_OFFSET, reg_val - 1);
+
+       /* TLOW - Value same as THIGH */
+       xiic_setreg32(i2c, XIIC_TLOW_REG_OFFSET, reg_val - 1);
+
+       /* TSUSTA */
+       reg_val = (timing_reg_values[index].tsusta * clk_in_mhz) / 1000;
+       xiic_setreg32(i2c, XIIC_TSUSTA_REG_OFFSET, reg_val - 1);
+
+       /* TSUSTO */
+       reg_val = (timing_reg_values[index].tsusto * clk_in_mhz) / 1000;
+       xiic_setreg32(i2c, XIIC_TSUSTO_REG_OFFSET, reg_val - 1);
+
+       /* THDSTA */
+       reg_val = (timing_reg_values[index].thdsta * clk_in_mhz) / 1000;
+       xiic_setreg32(i2c, XIIC_THDSTA_REG_OFFSET, reg_val - 1);
+
+       /* TSUDAT */
+       reg_val = (timing_reg_values[index].tsudat * clk_in_mhz) / 1000;
+       xiic_setreg32(i2c, XIIC_TSUDAT_REG_OFFSET, reg_val - 1);
+
+       /* TBUF */
+       reg_val = (timing_reg_values[index].tbuf * clk_in_mhz) / 1000;
+       xiic_setreg32(i2c, XIIC_TBUF_REG_OFFSET, reg_val - 1);
+
+       /* THDDAT */
+       xiic_setreg32(i2c, XIIC_THDDAT_REG_OFFSET, 1);
+
+       return 0;
+}
+
 static int xiic_reinit(struct xiic_i2c *i2c)
 {
        int ret;
 
        xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK);
 
+       ret = xiic_setclk(i2c);
+       if (ret)
+               return ret;
+
        /* Set receive Fifo depth to maximum (zero based). */
        xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1);
 
@@ -314,15 +485,72 @@ static void xiic_deinit(struct xiic_i2c *i2c)
        xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr & ~XIIC_CR_ENABLE_DEVICE_MASK);
 }
 
+static void xiic_smbus_block_read_setup(struct xiic_i2c *i2c)
+{
+       u8 rxmsg_len, rfd_set = 0;
+
+       /*
+        * Clear the I2C_M_RECV_LEN flag to avoid setting
+        * message length again
+        */
+       i2c->rx_msg->flags &= ~I2C_M_RECV_LEN;
+
+       /* Set smbus_block_read flag to identify in isr */
+       i2c->smbus_block_read = true;
+
+       /* Read byte from rx fifo and set message length */
+       rxmsg_len = xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET);
+
+       i2c->rx_msg->buf[i2c->rx_pos++] = rxmsg_len;
+
+       /* Check if received length is valid */
+       if (rxmsg_len <= I2C_SMBUS_BLOCK_MAX) {
+               /* Set Receive fifo depth */
+               if (rxmsg_len > IIC_RX_FIFO_DEPTH) {
+                       /*
+                        * When Rx msg len greater than or equal to Rx fifo capacity
+                        * Receive fifo depth should set to Rx fifo capacity minus 1
+                        */
+                       rfd_set = IIC_RX_FIFO_DEPTH - 1;
+                       i2c->rx_msg->len = rxmsg_len + 1;
+               } else if ((rxmsg_len == 1) ||
+                       (rxmsg_len == 0)) {
+                       /*
+                        * Minimum of 3 bytes required to exit cleanly. 1 byte
+                        * already received, Second byte is being received. Have
+                        * to set NACK in read_rx before receiving the last byte
+                        */
+                       rfd_set = 0;
+                       i2c->rx_msg->len = SMBUS_BLOCK_READ_MIN_LEN;
+               } else {
+                       /*
+                        * When Rx msg len less than Rx fifo capacity
+                        * Receive fifo depth should set to Rx msg len minus 2
+                        */
+                       rfd_set = rxmsg_len - 2;
+                       i2c->rx_msg->len = rxmsg_len + 1;
+               }
+               xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rfd_set);
+
+               return;
+       }
+
+       /* Invalid message length, trigger STATE_ERROR with tx_msg_len in ISR */
+       i2c->tx_msg->len = 3;
+       i2c->smbus_block_read = false;
+       dev_err(i2c->adap.dev.parent, "smbus_block_read Invalid msg length\n");
+}
+
 static void xiic_read_rx(struct xiic_i2c *i2c)
 {
-       u8 bytes_in_fifo;
+       u8 bytes_in_fifo, cr = 0, bytes_to_read = 0;
+       u32 bytes_rem = 0;
        int i;
 
        bytes_in_fifo = xiic_getreg8(i2c, XIIC_RFO_REG_OFFSET) + 1;
 
        dev_dbg(i2c->adap.dev.parent,
-               "%s entry, bytes in fifo: %d, msg: %d, SR: 0x%x, CR: 0x%x\n",
+               "%s entry, bytes in fifo: %d, rem: %d, SR: 0x%x, CR: 0x%x\n",
                __func__, bytes_in_fifo, xiic_rx_space(i2c),
                xiic_getreg8(i2c, XIIC_SR_REG_OFFSET),
                xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));
@@ -330,13 +558,58 @@ static void xiic_read_rx(struct xiic_i2c *i2c)
        if (bytes_in_fifo > xiic_rx_space(i2c))
                bytes_in_fifo = xiic_rx_space(i2c);
 
-       for (i = 0; i < bytes_in_fifo; i++)
+       bytes_to_read = bytes_in_fifo;
+
+       if (!i2c->dynamic) {
+               bytes_rem = xiic_rx_space(i2c) - bytes_in_fifo;
+
+               /* Set msg length if smbus_block_read */
+               if (i2c->rx_msg->flags & I2C_M_RECV_LEN) {
+                       xiic_smbus_block_read_setup(i2c);
+                       return;
+               }
+
+               if (bytes_rem > IIC_RX_FIFO_DEPTH) {
+                       bytes_to_read = bytes_in_fifo;
+               } else if (bytes_rem > 1) {
+                       bytes_to_read = bytes_rem - 1;
+               } else if (bytes_rem == 1) {
+                       bytes_to_read = 1;
+                       /* Set NACK in CR to indicate slave transmitter */
+                       cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET);
+                       xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr |
+                                       XIIC_CR_NO_ACK_MASK);
+               } else if (bytes_rem == 0) {
+                       bytes_to_read = bytes_in_fifo;
+
+                       /* Generate stop on the bus if it is last message */
+                       if (i2c->nmsgs == 1) {
+                               cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET);
+                               xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr &
+                                               ~XIIC_CR_MSMS_MASK);
+                       }
+
+                       /* Make TXACK=0, clean up for next transaction */
+                       cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET);
+                       xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr &
+                                       ~XIIC_CR_NO_ACK_MASK);
+               }
+       }
+
+       /* Read the fifo */
+       for (i = 0; i < bytes_to_read; i++) {
                i2c->rx_msg->buf[i2c->rx_pos++] =
                        xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET);
+       }
 
-       xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET,
-               (xiic_rx_space(i2c) > IIC_RX_FIFO_DEPTH) ?
-               IIC_RX_FIFO_DEPTH - 1 :  xiic_rx_space(i2c) - 1);
+       if (i2c->dynamic) {
+               u8 bytes;
+
+               /* Receive remaining bytes if less than fifo depth */
+               bytes = min_t(u8, xiic_rx_space(i2c), IIC_RX_FIFO_DEPTH);
+               bytes--;
+               xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, bytes);
+       }
 }
 
 static int xiic_tx_fifo_space(struct xiic_i2c *i2c)
@@ -360,7 +633,22 @@ static void xiic_fill_tx_fifo(struct xiic_i2c *i2c)
 
                if (!xiic_tx_space(i2c) && i2c->nmsgs == 1) {
                        /* last message in transfer -> STOP */
-                       data |= XIIC_TX_DYN_STOP_MASK;
+                       if (i2c->dynamic) {
+                               data |= XIIC_TX_DYN_STOP_MASK;
+                       } else {
+                               u8 cr;
+                               int status;
+
+                               /* Wait till FIFO is empty so STOP is sent last */
+                               status = xiic_wait_tx_empty(i2c);
+                               if (status)
+                                       return;
+
+                               /* Write to CR to stop */
+                               cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET);
+                               xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr &
+                                            ~XIIC_CR_MSMS_MASK);
+                       }
                        dev_dbg(i2c->adap.dev.parent, "%s TX STOP\n", __func__);
                }
                xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data);
@@ -401,7 +689,9 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
        dev_dbg(i2c->adap.dev.parent, "%s: SR: 0x%x, msg: %p, nmsgs: %d\n",
                __func__, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET),
                i2c->tx_msg, i2c->nmsgs);
-
+       dev_dbg(i2c->adap.dev.parent, "%s, ISR: 0x%x, CR: 0x%x\n",
+               __func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET),
+               xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));
 
        /* Service requesting interrupt */
        if ((pend & XIIC_INTR_ARB_LOST_MASK) ||
@@ -512,6 +802,12 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
                /* The bus is not busy, disable BusNotBusy interrupt */
                xiic_irq_dis(i2c, XIIC_INTR_BNB_MASK);
 
+               if (i2c->tx_msg && i2c->smbus_block_read) {
+                       i2c->smbus_block_read = false;
+                       /* Set requested message len=1 to indicate STATE_DONE */
+                       i2c->tx_msg->len = 1;
+               }
+
                if (!i2c->tx_msg)
                        goto out;
 
@@ -579,31 +875,113 @@ static int xiic_busy(struct xiic_i2c *i2c)
 static void xiic_start_recv(struct xiic_i2c *i2c)
 {
        u16 rx_watermark;
+       u8 cr = 0, rfd_set = 0;
        struct i2c_msg *msg = i2c->rx_msg = i2c->tx_msg;
 
-       /* Clear and enable Rx full interrupt. */
-       xiic_irq_clr_en(i2c, XIIC_INTR_RX_FULL_MASK | XIIC_INTR_TX_ERROR_MASK);
+       dev_dbg(i2c->adap.dev.parent, "%s entry, ISR: 0x%x, CR: 0x%x\n",
+               __func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET),
+               xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));
 
-       /* we want to get all but last byte, because the TX_ERROR IRQ is used
-        * to inidicate error ACK on the address, and negative ack on the last
-        * received byte, so to not mix them receive all but last.
-        * In the case where there is only one byte to receive
-        * we can check if ERROR and RX full is set at the same time
-        */
-       rx_watermark = msg->len;
-       if (rx_watermark > IIC_RX_FIFO_DEPTH)
-               rx_watermark = IIC_RX_FIFO_DEPTH;
-       xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, (u8)(rx_watermark - 1));
+       /* Disable Tx interrupts */
+       xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK | XIIC_INTR_TX_EMPTY_MASK);
+
+       if (i2c->dynamic) {
+               u8 bytes;
+               u16 val;
+
+               /* Clear and enable Rx full interrupt. */
+               xiic_irq_clr_en(i2c, XIIC_INTR_RX_FULL_MASK |
+                               XIIC_INTR_TX_ERROR_MASK);
+
+               /*
+                * We want to get all but last byte, because the TX_ERROR IRQ
+                * is used to indicate error ACK on the address, and
+                * negative ack on the last received byte, so to not mix
+                * them receive all but last.
+                * In the case where there is only one byte to receive
+                * we can check if ERROR and RX full is set at the same time
+                */
+               rx_watermark = msg->len;
+               bytes = min_t(u8, rx_watermark, IIC_RX_FIFO_DEPTH);
+
+               if (rx_watermark > 0)
+                       bytes--;
+               xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, bytes);
 
-       if (!(msg->flags & I2C_M_NOSTART))
                /* write the address */
                xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET,
-                       i2c_8bit_addr_from_msg(msg) | XIIC_TX_DYN_START_MASK);
+                             i2c_8bit_addr_from_msg(msg) |
+                             XIIC_TX_DYN_START_MASK);
+
+               /* If last message, include dynamic stop bit with length */
+               val = (i2c->nmsgs == 1) ? XIIC_TX_DYN_STOP_MASK : 0;
+               val |= msg->len;
+
+               xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, val);
+
+               xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK);
+       } else {
+               /*
+                * If previous message is Tx, make sure that Tx FIFO is empty
+                * before starting a new transfer as the repeated start in
+                * standard mode can corrupt the transaction if there are
+                * still bytes to be transmitted in FIFO
+                */
+               if (i2c->prev_msg_tx) {
+                       int status;
+
+                       status = xiic_wait_tx_empty(i2c);
+                       if (status)
+                               return;
+               }
 
-       xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK);
+               cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET);
 
-       xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET,
-               msg->len | ((i2c->nmsgs == 1) ? XIIC_TX_DYN_STOP_MASK : 0));
+               /* Set Receive fifo depth */
+               rx_watermark = msg->len;
+               if (rx_watermark > IIC_RX_FIFO_DEPTH) {
+                       rfd_set = IIC_RX_FIFO_DEPTH - 1;
+               } else if (rx_watermark == 1) {
+                       rfd_set = rx_watermark - 1;
+
+                       /* Set No_ACK, except for smbus_block_read */
+                       if (!(i2c->rx_msg->flags & I2C_M_RECV_LEN)) {
+                               /* Handle single byte transfer separately */
+                               cr |= XIIC_CR_NO_ACK_MASK;
+                       }
+               } else if (rx_watermark == 0) {
+                       rfd_set = rx_watermark;
+               } else {
+                       rfd_set = rx_watermark - 2;
+               }
+               /* Check if RSTA should be set */
+               if (cr & XIIC_CR_MSMS_MASK) {
+                       /* Already a master, RSTA should be set */
+                       xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, (cr |
+                                       XIIC_CR_REPEATED_START_MASK) &
+                                       ~(XIIC_CR_DIR_IS_TX_MASK));
+               }
+
+               xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rfd_set);
+
+               /* Clear and enable Rx full and transmit complete interrupts */
+               xiic_irq_clr_en(i2c, XIIC_INTR_RX_FULL_MASK |
+                               XIIC_INTR_TX_ERROR_MASK);
+
+               /* Write the address */
+               xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET,
+                             i2c_8bit_addr_from_msg(msg));
+
+               /* Write to Control Register,to start transaction in Rx mode */
+               if ((cr & XIIC_CR_MSMS_MASK) == 0) {
+                       xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, (cr |
+                                       XIIC_CR_MSMS_MASK)
+                                       & ~(XIIC_CR_DIR_IS_TX_MASK));
+               }
+               dev_dbg(i2c->adap.dev.parent, "%s end, ISR: 0x%x, CR: 0x%x\n",
+                       __func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET),
+                       xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));
+       }
 
        if (i2c->nmsgs == 1)
                /* very last, enable bus not busy as well */
@@ -611,10 +989,17 @@ static void xiic_start_recv(struct xiic_i2c *i2c)
 
        /* the message is tx:ed */
        i2c->tx_pos = msg->len;
+
+       /* Enable interrupts */
+       xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK);
+
+       i2c->prev_msg_tx = false;
 }
 
 static void xiic_start_send(struct xiic_i2c *i2c)
 {
+       u8 cr = 0;
+       u16 data;
        struct i2c_msg *msg = i2c->tx_msg;
 
        dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, len: %d",
@@ -623,24 +1008,70 @@ static void xiic_start_send(struct xiic_i2c *i2c)
                __func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET),
                xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));
 
-       if (!(msg->flags & I2C_M_NOSTART)) {
+       if (i2c->dynamic) {
                /* write the address */
-               u16 data = i2c_8bit_addr_from_msg(msg) |
-                       XIIC_TX_DYN_START_MASK;
-               if ((i2c->nmsgs == 1) && msg->len == 0)
+               data = i2c_8bit_addr_from_msg(msg) |
+                               XIIC_TX_DYN_START_MASK;
+
+               if (i2c->nmsgs == 1 && msg->len == 0)
                        /* no data and last message -> add STOP */
                        data |= XIIC_TX_DYN_STOP_MASK;
 
                xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data);
-       }
 
-       /* Clear any pending Tx empty, Tx Error and then enable them. */
-       xiic_irq_clr_en(i2c, XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_ERROR_MASK |
-               XIIC_INTR_BNB_MASK |
-               ((i2c->nmsgs > 1 || xiic_tx_space(i2c)) ?
-                       XIIC_INTR_TX_HALF_MASK : 0));
+               /* Clear any pending Tx empty, Tx Error and then enable them */
+               xiic_irq_clr_en(i2c, XIIC_INTR_TX_EMPTY_MASK |
+                               XIIC_INTR_TX_ERROR_MASK |
+                               XIIC_INTR_BNB_MASK |
+                               ((i2c->nmsgs > 1 || xiic_tx_space(i2c)) ?
+                               XIIC_INTR_TX_HALF_MASK : 0));
+
+               xiic_fill_tx_fifo(i2c);
+       } else {
+               /*
+                * If previous message is Tx, make sure that Tx FIFO is empty
+                * before starting a new transfer as the repeated start in
+                * standard mode can corrupt the transaction if there are
+                * still bytes to be transmitted in FIFO
+                */
+               if (i2c->prev_msg_tx) {
+                       int status;
+
+                       status = xiic_wait_tx_empty(i2c);
+                       if (status)
+                               return;
+               }
+               /* Check if RSTA should be set */
+               cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET);
+               if (cr & XIIC_CR_MSMS_MASK) {
+                       /* Already a master, RSTA should be set */
+                       xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, (cr |
+                                       XIIC_CR_REPEATED_START_MASK |
+                                       XIIC_CR_DIR_IS_TX_MASK) &
+                                       ~(XIIC_CR_NO_ACK_MASK));
+               }
+
+               /* Write address to FIFO */
+               data = i2c_8bit_addr_from_msg(msg);
+               xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data);
+
+               /* Fill fifo */
+               xiic_fill_tx_fifo(i2c);
 
-       xiic_fill_tx_fifo(i2c);
+               if ((cr & XIIC_CR_MSMS_MASK) == 0) {
+                       /* Start Tx by writing to CR */
+                       cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET);
+                       xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr |
+                                       XIIC_CR_MSMS_MASK |
+                                       XIIC_CR_DIR_IS_TX_MASK);
+               }
+
+               /* Clear any pending Tx empty, Tx Error and then enable them */
+               xiic_irq_clr_en(i2c, XIIC_INTR_TX_EMPTY_MASK |
+                               XIIC_INTR_TX_ERROR_MASK |
+                               XIIC_INTR_BNB_MASK);
+       }
+       i2c->prev_msg_tx = true;
 }
 
 static void __xiic_start_xfer(struct xiic_i2c *i2c)
@@ -666,7 +1097,8 @@ static void __xiic_start_xfer(struct xiic_i2c *i2c)
 
 static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num)
 {
-       int ret;
+       bool broken_read, max_read_len, smbus_blk_read;
+       int ret, count;
 
        mutex_lock(&i2c->lock);
 
@@ -679,6 +1111,34 @@ static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num)
        i2c->nmsgs = num;
        init_completion(&i2c->completion);
 
+       /* Decide standard mode or Dynamic mode */
+       i2c->dynamic = true;
+
+       /* Initialize prev message type */
+       i2c->prev_msg_tx = false;
+
+       /*
+        * Scan through nmsgs, use dynamic mode when none of the below three
+        * conditions occur. We need standard mode even if one condition holds
+        * true in the entire array of messages in a single transfer.
+        * If read transaction as dynamic mode is broken for delayed reads
+        * in xlnx,axi-iic-2.0 / xlnx,xps-iic-2.00.a IP versions.
+        * If read length is > 255 bytes.
+        * If smbus_block_read transaction.
+        */
+       for (count = 0; count < i2c->nmsgs; count++) {
+               broken_read = (i2c->quirks & DYNAMIC_MODE_READ_BROKEN_BIT) &&
+                               (i2c->tx_msg[count].flags & I2C_M_RD);
+               max_read_len = (i2c->tx_msg[count].flags & I2C_M_RD) &&
+                               (i2c->tx_msg[count].len > MAX_READ_LENGTH_DYNAMIC);
+               smbus_blk_read = (i2c->tx_msg[count].flags & I2C_M_RECV_LEN);
+
+               if (broken_read || max_read_len || smbus_blk_read) {
+                       i2c->dynamic = false;
+                       break;
+               }
+       }
+
        ret = xiic_reinit(i2c);
        if (!ret)
                __xiic_start_xfer(i2c);
@@ -714,10 +1174,6 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
                i2c->rx_msg = NULL;
                i2c->nmsgs = 0;
                err = -ETIMEDOUT;
-       } else if (err < 0) {   /* Completion error */
-               i2c->tx_msg = NULL;
-               i2c->rx_msg = NULL;
-               i2c->nmsgs = 0;
        } else {
                err = (i2c->state == STATE_DONE) ? num : -EIO;
        }
@@ -729,7 +1185,7 @@ static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 
 static u32 xiic_func(struct i2c_adapter *adap)
 {
-       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA;
 }
 
 static const struct i2c_algorithm xiic_algorithm = {
@@ -737,21 +1193,30 @@ static const struct i2c_algorithm xiic_algorithm = {
        .functionality = xiic_func,
 };
 
-static const struct i2c_adapter_quirks xiic_quirks = {
-       .max_read_len = 255,
-};
-
 static const struct i2c_adapter xiic_adapter = {
        .owner = THIS_MODULE,
        .class = I2C_CLASS_DEPRECATED,
        .algo = &xiic_algorithm,
-       .quirks = &xiic_quirks,
 };
 
+static const struct xiic_version_data xiic_2_00 = {
+       .quirks = DYNAMIC_MODE_READ_BROKEN_BIT,
+};
+
+#if defined(CONFIG_OF)
+static const struct of_device_id xiic_of_match[] = {
+       { .compatible = "xlnx,xps-iic-2.00.a", .data = &xiic_2_00 },
+       { .compatible = "xlnx,axi-iic-2.1", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, xiic_of_match);
+#endif
+
 static int xiic_i2c_probe(struct platform_device *pdev)
 {
        struct xiic_i2c *i2c;
        struct xiic_i2c_platform_data *pdata;
+       const struct of_device_id *match;
        struct resource *res;
        int ret, irq;
        u8 i;
@@ -761,6 +1226,13 @@ static int xiic_i2c_probe(struct platform_device *pdev)
        if (!i2c)
                return -ENOMEM;
 
+       match = of_match_node(xiic_of_match, pdev->dev.of_node);
+       if (match && match->data) {
+               const struct xiic_version_data *data = match->data;
+
+               i2c->quirks = data->quirks;
+       }
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        i2c->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(i2c->base))
@@ -798,6 +1270,15 @@ static int xiic_i2c_probe(struct platform_device *pdev)
        pm_runtime_use_autosuspend(i2c->dev);
        pm_runtime_set_active(i2c->dev);
        pm_runtime_enable(i2c->dev);
+
+       /* SCL frequency configuration */
+       i2c->input_clk = clk_get_rate(i2c->clk);
+       ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+                                  &i2c->i2c_clk);
+       /* If clock-frequency not specified in DT, do not configure in SW */
+       if (ret || i2c->i2c_clk > I2C_MAX_FAST_MODE_PLUS_FREQ)
+               i2c->i2c_clk = 0;
+
        ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
                                        xiic_process, IRQF_ONESHOT,
                                        pdev->name, i2c);
@@ -841,6 +1322,9 @@ static int xiic_i2c_probe(struct platform_device *pdev)
                        i2c_new_client_device(&i2c->adap, pdata->devices + i);
        }
 
+       dev_dbg(&pdev->dev, "mmio %08lx irq %d scl clock frequency %d\n",
+               (unsigned long)res->start, irq, i2c->i2c_clk);
+
        return 0;
 
 err_clk_dis:
@@ -875,14 +1359,6 @@ static int xiic_i2c_remove(struct platform_device *pdev)
        return 0;
 }
 
-#if defined(CONFIG_OF)
-static const struct of_device_id xiic_of_match[] = {
-       { .compatible = "xlnx,xps-iic-2.00.a", },
-       {},
-};
-MODULE_DEVICE_TABLE(of, xiic_of_match);
-#endif
-
 static int __maybe_unused xiic_i2c_runtime_suspend(struct device *dev)
 {
        struct xiic_i2c *i2c = dev_get_drvdata(dev);
index 734d8e6ad4a98a9c04ca2a6eb11171d149d24b8d..cb5fa971d67e2a004a2be854e4b94387fff0404b 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/devinfo.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_wakeirq.h>
@@ -282,7 +283,9 @@ static void i2c_gpio_init_pinctrl_recovery(struct i2c_adapter *adap)
 {
        struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
        struct device *dev = &adap->dev;
-       struct pinctrl *p = bri->pinctrl;
+       struct pinctrl *p = bri->pinctrl ?: dev_pinctrl(dev->parent);
+
+       bri->pinctrl = p;
 
        /*
         * we can't change states without pinctrl, so remove the states if
index ab0adaa130dae31da7658798481694628af270af..107623c4cc14aaf95e5bf930f45ca8a179884d51 100644 (file)
@@ -653,12 +653,12 @@ static int i2cdev_attach_adapter(struct device *dev, void *dummy)
        int res;
 
        if (dev->type != &i2c_adapter_type)
-               return 0;
+               return NOTIFY_DONE;
        adap = to_i2c_adapter(dev);
 
        i2c_dev = get_free_i2c_dev(adap);
        if (IS_ERR(i2c_dev))
-               return PTR_ERR(i2c_dev);
+               return NOTIFY_DONE;
 
        cdev_init(&i2c_dev->cdev, &i2cdev_fops);
        i2c_dev->cdev.owner = THIS_MODULE;
@@ -678,11 +678,11 @@ static int i2cdev_attach_adapter(struct device *dev, void *dummy)
                goto err_put_i2c_dev;
 
        pr_debug("adapter [%s] registered as minor %d\n", adap->name, adap->nr);
-       return 0;
+       return NOTIFY_OK;
 
 err_put_i2c_dev:
        put_i2c_dev(i2c_dev, false);
-       return res;
+       return NOTIFY_DONE;
 }
 
 static int i2cdev_detach_adapter(struct device *dev, void *dummy)
@@ -691,17 +691,17 @@ static int i2cdev_detach_adapter(struct device *dev, void *dummy)
        struct i2c_dev *i2c_dev;
 
        if (dev->type != &i2c_adapter_type)
-               return 0;
+               return NOTIFY_DONE;
        adap = to_i2c_adapter(dev);
 
        i2c_dev = i2c_dev_get_by_minor(adap->nr);
        if (!i2c_dev) /* attach_adapter must have failed */
-               return 0;
+               return NOTIFY_DONE;
 
        put_i2c_dev(i2c_dev, true);
 
        pr_debug("adapter [%s] unregistered\n", adap->name);
-       return 0;
+       return NOTIFY_OK;
 }
 
 static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
@@ -716,7 +716,7 @@ static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
                return i2cdev_detach_adapter(dev, NULL);
        }
 
-       return 0;
+       return NOTIFY_DONE;
 }
 
 static struct notifier_block i2cdev_notifier = {
index 9e8b559e125305a7f1f17966bdfa70b1bdf70c56..bb6653af4f92b96ef04d0a90d9ff586c940d0498 100644 (file)
@@ -18,6 +18,8 @@ struct device;
 
 #ifdef CONFIG_PINCTRL
 
+#include <linux/device.h>
+
 /* The device core acts as a consumer toward pinctrl */
 #include <linux/pinctrl/consumer.h>
 
@@ -44,6 +46,14 @@ struct dev_pin_info {
 extern int pinctrl_bind_pins(struct device *dev);
 extern int pinctrl_init_done(struct device *dev);
 
+static inline struct pinctrl *dev_pinctrl(struct device *dev)
+{
+       if (!dev->pins)
+               return NULL;
+
+       return dev->pins->p;
+}
+
 #else
 
 /* Stubs if we're not using pinctrl */
@@ -58,5 +68,10 @@ static inline int pinctrl_init_done(struct device *dev)
        return 0;
 }
 
+static inline struct pinctrl *dev_pinctrl(struct device *dev)
+{
+       return NULL;
+}
+
 #endif /* CONFIG_PINCTRL */
 #endif /* PINCTRL_DEVINFO_H */
index a907774fd177f83a31abd5f20b3153690ee0f2d2..545639bcca72a14cc2ff2055bf32f9370ae17ecf 100644 (file)
  *     isn't actively driven high when setting the output value high.
  *     gpio_get_value() must return the actual pin state even if the
  *     pin is configured as an output.
+ * @sda_is_output_only: SDA output drivers can't be turned off.
+ *     This is for clients that can only read SDA/SCL.
+ * @sda_has_no_pullup: SDA is used in a non-compliant way and has no pull-up.
+ *     Therefore disable open-drain.
  * @scl_is_open_drain: SCL is set up as open drain. Same requirements
  *     as for sda_is_open_drain apply.
  * @scl_is_output_only: SCL output drivers cannot be turned off.
+ * @scl_has_no_pullup: SCL is used in a non-compliant way and has no pull-up.
+ *     Therefore disable open-drain.
  */
 struct i2c_gpio_platform_data {
        int             udelay;
        int             timeout;
        unsigned int    sda_is_open_drain:1;
+       unsigned int    sda_is_output_only:1;
+       unsigned int    sda_has_no_pullup:1;
        unsigned int    scl_is_open_drain:1;
        unsigned int    scl_is_output_only:1;
+       unsigned int    scl_has_no_pullup:1;
 };
 
 #endif /* _LINUX_I2C_GPIO_H */