From patchwork Tue Mar 23 04:33:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Packham X-Patchwork-Id: 407169 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5DC55C433E0 for ; Tue, 23 Mar 2021 04:34:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2B7F3619A5 for ; Tue, 23 Mar 2021 04:34:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229448AbhCWEe1 (ORCPT ); Tue, 23 Mar 2021 00:34:27 -0400 Received: from gate2.alliedtelesis.co.nz ([202.36.163.20]:39014 "EHLO gate2.alliedtelesis.co.nz" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229500AbhCWEdv (ORCPT ); Tue, 23 Mar 2021 00:33:51 -0400 Received: from svr-chch-seg1.atlnz.lc (mmarshal3.atlnz.lc [10.32.18.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by gate2.alliedtelesis.co.nz (Postfix) with ESMTPS id D80F2891AE; Tue, 23 Mar 2021 17:33:47 +1300 (NZDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alliedtelesis.co.nz; s=mail181024; t=1616474027; bh=vSTLpwh5K444l5BGf/dQ0YOvwBnK3lHUEiyx1CVu4MY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=xdm/KCwCMFtQGvsSZGGyQLdJhUW9VpRb9Nkc3YZriMTI7+C79bwx5gv4oWS7DauK8 6em6ot4Z9D8vkUHccV/OubN3gfxQ2Q9IguW63MBKW+WOd4ThUCVb/urYFuDrdEOFTJ 6Df6zHrJGrNh1f3XHrZ3zOQtVNTaYQVZ6KyFASDcMBE74X+YcW6tzqsUvII1D51UzA yIndODVmQATo/TQudqmsCUH+ZCn1TrUtm7SC5ma2byt3jKwpn79IGJR19wio/KJ2hA oOFGbksPdU6Cu6YLeXmftYFdzVGuMtcGf8UbeZfwx5EfrNQyhAshSWyI867UMjcntK pFD7h8JdoIE/A== Received: from smtp (Not Verified[10.32.16.33]) by svr-chch-seg1.atlnz.lc with Trustwave SEG (v8, 2, 6, 11305) id ; Tue, 23 Mar 2021 17:33:47 +1300 Received: from chrisp-dl.ws.atlnz.lc (chrisp-dl.ws.atlnz.lc [10.33.22.20]) by smtp (Postfix) with ESMTP id 4049513EED4; Tue, 23 Mar 2021 17:34:03 +1300 (NZDT) Received: by chrisp-dl.ws.atlnz.lc (Postfix, from userid 1030) id B350228409A; Tue, 23 Mar 2021 17:33:47 +1300 (NZDT) From: Chris Packham To: robh+dt@kernel.org, linux@roeck-us.net, wsa@kernel.org, jdelvare@suse.com Cc: linux-i2c@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Chris Packham Subject: [PATCH 1/6] dt-bindings: i2c-mpc: Document interrupt property as required Date: Tue, 23 Mar 2021 17:33:26 +1300 Message-Id: <20210323043331.21878-2-chris.packham@alliedtelesis.co.nz> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210323043331.21878-1-chris.packham@alliedtelesis.co.nz> References: <20210323043331.21878-1-chris.packham@alliedtelesis.co.nz> MIME-Version: 1.0 X-SEG-SpamProfiler-Analysis: v=2.3 cv=GfppYjfL c=1 sm=1 tr=0 a=KLBiSEs5mFS1a/PbTCJxuA==:117 a=dESyimp9J3IA:10 a=yq7alYDTZcx5lnFy0mkA:9 X-SEG-SpamProfiler-Score: 0 x-atlnz-ls: pat Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org All of the in-tree device-trees that use the one of the compatible strings from i2c-mpc.c supply an interrupts property. Make this property mandatory to aid refactoring the driver. Signed-off-by: Chris Packham --- Documentation/devicetree/bindings/i2c/i2c-mpc.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-mpc.txt b/Documentation/devicetree/bindings/i2c/i2c-mpc.txt index 42a390526957..b15acb43d84d 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mpc.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-mpc.txt @@ -7,14 +7,14 @@ Required properties : compatible processor, e.g. mpc8313, mpc8543, mpc8544, mpc5121, mpc5200 or mpc5200b. For the mpc5121, an additional node "fsl,mpc5121-i2c-ctrl" is required as shown in the example below. - -Recommended properties : - - interrupts : where a is the interrupt number and b is a field that represents an encoding of the sense and level information for the interrupt. This should be encoded based on the information in section 2) depending on the type of interrupt controller you have. + +Recommended properties : + - fsl,preserve-clocking : boolean; if defined, the clock settings from the bootloader are preserved (not touched). - clock-frequency : desired I2C bus clock frequency in Hz. From patchwork Tue Mar 23 04:33:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Packham X-Patchwork-Id: 407167 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F3537C433E8 for ; Tue, 23 Mar 2021 04:34:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BB460619C8 for ; Tue, 23 Mar 2021 04:34:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229693AbhCWEe2 (ORCPT ); Tue, 23 Mar 2021 00:34:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33470 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229574AbhCWEdy (ORCPT ); Tue, 23 Mar 2021 00:33:54 -0400 Received: from gate2.alliedtelesis.co.nz (gate2.alliedtelesis.co.nz [IPv6:2001:df5:b000:5::4]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1BA19C061574 for ; Mon, 22 Mar 2021 21:33:53 -0700 (PDT) Received: from svr-chch-seg1.atlnz.lc (mmarshal3.atlnz.lc [10.32.18.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by gate2.alliedtelesis.co.nz (Postfix) with ESMTPS id 32225891AF; Tue, 23 Mar 2021 17:33:48 +1300 (NZDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alliedtelesis.co.nz; s=mail181024; t=1616474028; bh=ofwmam07g4vU+wSIrGHnrwuKPgIIlDUs4BnvCAVNNKs=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=k5k9uuV9uvI+KQL8nStl2IvmNntIC7FuA4eWSATve0hOTzXbHxVPNj9tuKrFlGKkD pKEW23LyALmzHoPs7f1htWDiP7Jpv3piZ43OTnIKL5t5RLc4vwqXo4G9GuwEOyuNop HkP4BgkNppjQzV5tg8cuP5FZTkqNBlU7mQvsaiuTygUYn5t9NolhZNlvYK+kcu0Rz5 5s23nyVfGAAdemC366QHJw0NwErPHLyr1KYpPk942iBfir3mPgTgUhPRq4kvwSaLHD Aohw+aSrM5PThdyHCB+9hKbVZ1CC0GztxU2bKwmTfVptkXduug9+p56X7aY5e8SEdU QdAMFubZCuLHw== Received: from smtp (Not Verified[10.32.16.33]) by svr-chch-seg1.atlnz.lc with Trustwave SEG (v8, 2, 6, 11305) id ; Tue, 23 Mar 2021 17:33:47 +1300 Received: from chrisp-dl.ws.atlnz.lc (chrisp-dl.ws.atlnz.lc [10.33.22.20]) by smtp (Postfix) with ESMTP id 785BC13EED4; Tue, 23 Mar 2021 17:34:03 +1300 (NZDT) Received: by chrisp-dl.ws.atlnz.lc (Postfix, from userid 1030) id EB59628409A; Tue, 23 Mar 2021 17:33:47 +1300 (NZDT) From: Chris Packham To: robh+dt@kernel.org, linux@roeck-us.net, wsa@kernel.org, jdelvare@suse.com Cc: linux-i2c@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Chris Packham Subject: [PATCH 2/6] dt-bindings: i2c: convert i2c-mpc to json-schema Date: Tue, 23 Mar 2021 17:33:27 +1300 Message-Id: <20210323043331.21878-3-chris.packham@alliedtelesis.co.nz> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210323043331.21878-1-chris.packham@alliedtelesis.co.nz> References: <20210323043331.21878-1-chris.packham@alliedtelesis.co.nz> MIME-Version: 1.0 X-SEG-SpamProfiler-Analysis: v=2.3 cv=GfppYjfL c=1 sm=1 tr=0 a=KLBiSEs5mFS1a/PbTCJxuA==:117 a=dESyimp9J3IA:10 a=gEfo2CItAAAA:8 a=Enga5HRRDKvgB7_1_YsA:9 a=ezc__IB3qI4VJWUD:21 a=iBSJKkvYTiTODKpV:21 a=sptkURWiP4Gy88Gu7hUp:22 X-SEG-SpamProfiler-Score: 0 x-atlnz-ls: pat Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org Convert i2c-mpc to YAML. Signed-off-by: Chris Packham --- .../devicetree/bindings/i2c/i2c-mpc.txt | 62 ------------ .../devicetree/bindings/i2c/i2c-mpc.yaml | 99 +++++++++++++++++++ 2 files changed, 99 insertions(+), 62 deletions(-) delete mode 100644 Documentation/devicetree/bindings/i2c/i2c-mpc.txt create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mpc.yaml diff --git a/Documentation/devicetree/bindings/i2c/i2c-mpc.txt b/Documentation/devicetree/bindings/i2c/i2c-mpc.txt deleted file mode 100644 index b15acb43d84d..000000000000 --- a/Documentation/devicetree/bindings/i2c/i2c-mpc.txt +++ /dev/null @@ -1,62 +0,0 @@ -* I2C - -Required properties : - - - reg : Offset and length of the register set for the device - - compatible : should be "fsl,CHIP-i2c" where CHIP is the name of a - compatible processor, e.g. mpc8313, mpc8543, mpc8544, mpc5121, - mpc5200 or mpc5200b. For the mpc5121, an additional node - "fsl,mpc5121-i2c-ctrl" is required as shown in the example below. - - interrupts : where a is the interrupt number and b is a - field that represents an encoding of the sense and level - information for the interrupt. This should be encoded based on - the information in section 2) depending on the type of interrupt - controller you have. - -Recommended properties : - - - fsl,preserve-clocking : boolean; if defined, the clock settings - from the bootloader are preserved (not touched). - - clock-frequency : desired I2C bus clock frequency in Hz. - - fsl,timeout : I2C bus timeout in microseconds. - -Examples : - - /* MPC5121 based board */ - i2c@1740 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,mpc5121-i2c", "fsl-i2c"; - reg = <0x1740 0x20>; - interrupts = <11 0x8>; - interrupt-parent = <&ipic>; - clock-frequency = <100000>; - }; - - i2ccontrol@1760 { - compatible = "fsl,mpc5121-i2c-ctrl"; - reg = <0x1760 0x8>; - }; - - /* MPC5200B based board */ - i2c@3d00 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c","fsl-i2c"; - reg = <0x3d00 0x40>; - interrupts = <2 15 0>; - interrupt-parent = <&mpc5200_pic>; - fsl,preserve-clocking; - }; - - /* MPC8544 base board */ - i2c@3100 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "fsl,mpc8544-i2c", "fsl-i2c"; - reg = <0x3100 0x100>; - interrupts = <43 2>; - interrupt-parent = <&mpic>; - clock-frequency = <400000>; - fsl,timeout = <10000>; - }; diff --git a/Documentation/devicetree/bindings/i2c/i2c-mpc.yaml b/Documentation/devicetree/bindings/i2c/i2c-mpc.yaml new file mode 100644 index 000000000000..97cea8a817ea --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/i2c-mpc.yaml @@ -0,0 +1,99 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/i2c-mpc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: I2C-Bus adapter for MPC824x/83xx/85xx/86xx/512x/52xx SoCs + +maintainers: + - Chris Packham + +allOf: + - $ref: /schemas/i2c/i2c-controller.yaml# + +properties: + compatible: + anyOf: + - items: + - enum: + - mpc5200-i2c + - fsl,mpc5200b-i2c + - fsl,mpc5200-i2c + - fsl,mpc5121-i2c + - fsl,mpc8313-i2c + - fsl,mpc8543-i2c + - fsl,mpc8544-i2c + + - const: fsl-i2c + + - contains: + const: fsl-i2c + minItems: 1 + maxItems: 4 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + fsl,preserve-clocking: + $ref: /schemas/types.yaml#/definitions/flag + description: | + if defined, the clock settings from the bootloader are + preserved (not touched) + + fsl,timeout: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + I2C bus timeout in microseconds + +required: + - compatible + - reg + - interrupts + +unevaluatedProperties: false + +examples: + - | + /* MPC5121 based board */ + i2c@1740 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,mpc5121-i2c", "fsl-i2c"; + reg = <0x1740 0x20>; + interrupts = <11 0x8>; + interrupt-parent = <&ipic>; + clock-frequency = <100000>; + }; + + i2ccontrol@1760 { + compatible = "fsl,mpc5121-i2c-ctrl"; + reg = <0x1760 0x8>; + }; + + /* MPC5200B based board */ + i2c@3d00 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,mpc5200b-i2c", "fsl,mpc5200-i2c", "fsl-i2c"; + reg = <0x3d00 0x40>; + interrupts = <2 15 0>; + interrupt-parent = <&mpc5200_pic>; + fsl,preserve-clocking; + }; + + /* MPC8544 base board */ + i2c@3100 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,mpc8544-i2c", "fsl-i2c"; + reg = <0x3100 0x100>; + interrupts = <43 2>; + interrupt-parent = <&mpic>; + clock-frequency = <400000>; + fsl,timeout = <10000>; + }; +... From patchwork Tue Mar 23 04:33:28 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Packham X-Patchwork-Id: 408455 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0C5F2C433EA for ; Tue, 23 Mar 2021 04:34:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CB0D461994 for ; Tue, 23 Mar 2021 04:34:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229631AbhCWEe3 (ORCPT ); Tue, 23 Mar 2021 00:34:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33488 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229614AbhCWEdy (ORCPT ); Tue, 23 Mar 2021 00:33:54 -0400 Received: from gate2.alliedtelesis.co.nz (gate2.alliedtelesis.co.nz [IPv6:2001:df5:b000:5::4]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3C8CDC0613D8 for ; Mon, 22 Mar 2021 21:33:53 -0700 (PDT) Received: from svr-chch-seg1.atlnz.lc (mmarshal3.atlnz.lc [10.32.18.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by gate2.alliedtelesis.co.nz (Postfix) with ESMTPS id 37CA3891B0; Tue, 23 Mar 2021 17:33:48 +1300 (NZDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alliedtelesis.co.nz; s=mail181024; t=1616474028; bh=SN6b5LCcIucEvVtwLqIzgxrbW6usrE1b4VxLa99rvz8=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Qw7ZRVQJPEusslfNI7H2jZa4b/qcLdv+PFz7uM4tDGf6geerD0/nHqF6WAqRbUF3M zXYgHJ313sglfyPCfsPZGIVRJ8gNQ3df9t2f20HsAfx+0gVhdr88NmjxT3R3proaXG +/gpej9yOV9j2vnlvV1HpE5SbGolnPQCcLubg8Nl425TXgn6x+CipKQ6XwTODAzjVD E6IgBGfhioreYY6sVezcYIejYRJwcMVVn+eQSIkOfkWerFBX2Y0IUOqYrD5DKwtaaI g/VZXB+IMm5jq+YHbgYZMJ3zWDIGlmnvDXqlRO7S+zEIRg386nKuE8XZ6NFxE+Mgsf 86nb0815vozGA== Received: from smtp (Not Verified[10.32.16.33]) by svr-chch-seg1.atlnz.lc with Trustwave SEG (v8, 2, 6, 11305) id ; Tue, 23 Mar 2021 17:33:48 +1300 Received: from chrisp-dl.ws.atlnz.lc (chrisp-dl.ws.atlnz.lc [10.33.22.20]) by smtp (Postfix) with ESMTP id 9BFC613EED4; Tue, 23 Mar 2021 17:34:03 +1300 (NZDT) Received: by chrisp-dl.ws.atlnz.lc (Postfix, from userid 1030) id 1AD6328409A; Tue, 23 Mar 2021 17:33:48 +1300 (NZDT) From: Chris Packham To: robh+dt@kernel.org, linux@roeck-us.net, wsa@kernel.org, jdelvare@suse.com Cc: linux-i2c@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Chris Packham Subject: [PATCH 3/6] i2c: mpc: Make use of i2c_recover_bus() Date: Tue, 23 Mar 2021 17:33:28 +1300 Message-Id: <20210323043331.21878-4-chris.packham@alliedtelesis.co.nz> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210323043331.21878-1-chris.packham@alliedtelesis.co.nz> References: <20210323043331.21878-1-chris.packham@alliedtelesis.co.nz> MIME-Version: 1.0 X-SEG-SpamProfiler-Analysis: v=2.3 cv=GfppYjfL c=1 sm=1 tr=0 a=KLBiSEs5mFS1a/PbTCJxuA==:117 a=dESyimp9J3IA:10 a=SdC2vBNBQt3qShdCGKMA:9 X-SEG-SpamProfiler-Score: 0 x-atlnz-ls: pat Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org Move the existing calls of mpc_i2c_fixup() to a recovery function registered via bus_recovery_info. This makes it more obvious that recovery is supported and allows for a future where recovery is triggered by the i2c core. Signed-off-by: Chris Packham --- drivers/i2c/busses/i2c-mpc.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index d94f05c8b8b7..6a0d55e9e8e3 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -586,7 +586,7 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) if ((status & (CSR_MCF | CSR_MBB | CSR_RXAK)) != 0) { writeb(status & ~CSR_MAL, i2c->base + MPC_I2C_SR); - mpc_i2c_fixup(i2c); + i2c_recover_bus(&i2c->adap); } return -EIO; } @@ -622,7 +622,7 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) if ((status & (CSR_MCF | CSR_MBB | CSR_RXAK)) != 0) { writeb(status & ~CSR_MAL, i2c->base + MPC_I2C_SR); - mpc_i2c_fixup(i2c); + i2c_recover_bus(&i2c->adap); } return -EIO; } @@ -637,6 +637,15 @@ static u32 mpc_functionality(struct i2c_adapter *adap) | I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL; } +static int fsl_i2c_bus_recovery(struct i2c_adapter *adap) +{ + struct mpc_i2c *i2c = i2c_get_adapdata(adap); + + mpc_i2c_fixup(i2c); + + return 0; +} + static const struct i2c_algorithm mpc_algo = { .master_xfer = mpc_xfer, .functionality = mpc_functionality, @@ -648,6 +657,10 @@ static struct i2c_adapter mpc_ops = { .timeout = HZ, }; +static struct i2c_bus_recovery_info fsl_i2c_recovery_info = { + .recover_bus = fsl_i2c_bus_recovery, +}; + static const struct of_device_id mpc_i2c_of_match[]; static int fsl_i2c_probe(struct platform_device *op) { @@ -740,6 +753,7 @@ static int fsl_i2c_probe(struct platform_device *op) i2c_set_adapdata(&i2c->adap, i2c); i2c->adap.dev.parent = &op->dev; i2c->adap.dev.of_node = of_node_get(op->dev.of_node); + i2c->adap.bus_recovery_info = &fsl_i2c_recovery_info; result = i2c_add_adapter(&i2c->adap); if (result < 0) From patchwork Tue Mar 23 04:33:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Packham X-Patchwork-Id: 408454 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 65426C433EC for ; Tue, 23 Mar 2021 04:34:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4DC91619A5 for ; Tue, 23 Mar 2021 04:34:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229614AbhCWEea (ORCPT ); Tue, 23 Mar 2021 00:34:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33476 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229591AbhCWEdy (ORCPT ); Tue, 23 Mar 2021 00:33:54 -0400 Received: from gate2.alliedtelesis.co.nz (gate2.alliedtelesis.co.nz [IPv6:2001:df5:b000:5::4]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2E979C061764 for ; Mon, 22 Mar 2021 21:33:53 -0700 (PDT) Received: from svr-chch-seg1.atlnz.lc (mmarshal3.atlnz.lc [10.32.18.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by gate2.alliedtelesis.co.nz (Postfix) with ESMTPS id 656D1891B1; Tue, 23 Mar 2021 17:33:48 +1300 (NZDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alliedtelesis.co.nz; s=mail181024; t=1616474028; bh=cb+6xTb6XxXHAX7wUMJtQkeuuwjPkSKpxqCPPV8I6Lk=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=mCjm6WyTKGJUb1R7jwvJ/Ms9OUzesdnE1IgSTEZkujHOX2zl2g3N3kDhu/0M6uQZQ foy9MjgXyBBzKRa+BuAV9zNnXtvso1+Qso9SR+Jg7e2lx/yXLXoASsDjoQoypQq5X+ HuEmMf5odb1+JZNjBvGwIkir61qYvfYl1rV3nzjWAr4+OYkbsUtbzGTTnILCg1rw7j xz9FpbCnKVmRPcXVEWfQ8i0kFqa1WTc6OUT38kNVpHD+nxqNm/cShC88IIGZuOVME2 RmkdrE756IxdMt/jPOrhyiknUTpd7FO5UF6yblo5Aj8MeD2Vy1m2tPSj1TGEd32dOh z/REQLmxeR1xw== Received: from smtp (Not Verified[10.32.16.33]) by svr-chch-seg1.atlnz.lc with Trustwave SEG (v8, 2, 6, 11305) id ; Tue, 23 Mar 2021 17:33:48 +1300 Received: from chrisp-dl.ws.atlnz.lc (chrisp-dl.ws.atlnz.lc [10.33.22.20]) by smtp (Postfix) with ESMTP id C161313EED4; Tue, 23 Mar 2021 17:34:03 +1300 (NZDT) Received: by chrisp-dl.ws.atlnz.lc (Postfix, from userid 1030) id 4028528409A; Tue, 23 Mar 2021 17:33:48 +1300 (NZDT) From: Chris Packham To: robh+dt@kernel.org, linux@roeck-us.net, wsa@kernel.org, jdelvare@suse.com Cc: linux-i2c@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Chris Packham Subject: [PATCH 4/6] i2c: mpc: make interrupt mandatory and remove polling code Date: Tue, 23 Mar 2021 17:33:29 +1300 Message-Id: <20210323043331.21878-5-chris.packham@alliedtelesis.co.nz> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210323043331.21878-1-chris.packham@alliedtelesis.co.nz> References: <20210323043331.21878-1-chris.packham@alliedtelesis.co.nz> MIME-Version: 1.0 X-SEG-SpamProfiler-Analysis: v=2.3 cv=GfppYjfL c=1 sm=1 tr=0 a=KLBiSEs5mFS1a/PbTCJxuA==:117 a=dESyimp9J3IA:10 a=T_qO__Z0IpnnGzeVBEwA:9 X-SEG-SpamProfiler-Score: 0 x-atlnz-ls: pat Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org All the in-tree dts files that use one of the compatible strings from i2c-mpc.c provide an interrupt property. By making this mandatory we can simplify the code. Signed-off-by: Chris Packham --- drivers/i2c/busses/i2c-mpc.c | 51 ++++++++++++++---------------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 6a0d55e9e8e3..5b746a898e8e 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -123,37 +123,21 @@ static void mpc_i2c_fixup(struct mpc_i2c *i2c) static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) { - unsigned long orig_jiffies = jiffies; u32 cmd_err; - int result = 0; + int result; - if (!i2c->irq) { - while (!(readb(i2c->base + MPC_I2C_SR) & CSR_MIF)) { - schedule(); - if (time_after(jiffies, orig_jiffies + timeout)) { - dev_dbg(i2c->dev, "timeout\n"); - writeccr(i2c, 0); - result = -ETIMEDOUT; - break; - } - } - cmd_err = readb(i2c->base + MPC_I2C_SR); - writeb(0, i2c->base + MPC_I2C_SR); - } else { - /* Interrupt mode */ - result = wait_event_timeout(i2c->queue, + result = wait_event_timeout(i2c->queue, (i2c->interrupt & CSR_MIF), timeout); - if (unlikely(!(i2c->interrupt & CSR_MIF))) { - dev_dbg(i2c->dev, "wait timeout\n"); - writeccr(i2c, 0); - result = -ETIMEDOUT; - } - - cmd_err = i2c->interrupt; - i2c->interrupt = 0; + if (unlikely(!(i2c->interrupt & CSR_MIF))) { + dev_dbg(i2c->dev, "wait timeout\n"); + writeccr(i2c, 0); + result = -ETIMEDOUT; } + cmd_err = i2c->interrupt; + i2c->interrupt = 0; + if (result < 0) return result; @@ -694,13 +678,16 @@ static int fsl_i2c_probe(struct platform_device *op) } i2c->irq = irq_of_parse_and_map(op->dev.of_node, 0); - if (i2c->irq) { /* no i2c->irq implies polling */ - result = request_irq(i2c->irq, mpc_i2c_isr, - IRQF_SHARED, "i2c-mpc", i2c); - if (result < 0) { - dev_err(i2c->dev, "failed to attach interrupt\n"); - goto fail_request; - } + if (i2c->irq < 0) { + result = i2c->irq; + goto fail_map; + } + + result = request_irq(i2c->irq, mpc_i2c_isr, + IRQF_SHARED, "i2c-mpc", i2c); + if (result < 0) { + dev_err(i2c->dev, "failed to attach interrupt\n"); + goto fail_request; } /* From patchwork Tue Mar 23 04:33:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Packham X-Patchwork-Id: 407168 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 95867C433E2 for ; Tue, 23 Mar 2021 04:34:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 83053619A5 for ; Tue, 23 Mar 2021 04:34:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229728AbhCWEe2 (ORCPT ); Tue, 23 Mar 2021 00:34:28 -0400 Received: from gate2.alliedtelesis.co.nz ([202.36.163.20]:39048 "EHLO gate2.alliedtelesis.co.nz" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229547AbhCWEdx (ORCPT ); Tue, 23 Mar 2021 00:33:53 -0400 Received: from svr-chch-seg1.atlnz.lc (mmarshal3.atlnz.lc [10.32.18.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by gate2.alliedtelesis.co.nz (Postfix) with ESMTPS id 83C2F891B2; Tue, 23 Mar 2021 17:33:48 +1300 (NZDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alliedtelesis.co.nz; s=mail181024; t=1616474028; bh=lXzkv/KDPQjWWEnwXmHPF8yt1n77/EQsw/crJ9mVwf4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=ZQ0fuAqM/eFxF09+bbzPBS+2jhOCOLgWrCkT3VIgSRl6bC/It5vk1u+G8xgvz6Nzz 2Om1pAuL+Q5DCBCrDTnLozYIehyWJZ4GNkmqWlidsW31Z3Yzr58vP/ET42dS7LkCEg d8yLDfPm3+7Dnn1aDQKu2js/HcYe+vP2liQt+q0iAT8UmI+mZ4rIDyk5JrMen5ScYQ kh92ymvTKkzP0a4P+TBnyEMMBwxke4WMGsxJK/djRGvg2CjfKDMXHmgSiY1e6pjnNS SQlKq0DNGkXFyXrBBKA0H2hnWFwxYET0X5oo5p8uiSB4i71Plwhta73m/HzG5pGP9X tae0FRvJcazzQ== Received: from smtp (Not Verified[10.32.16.33]) by svr-chch-seg1.atlnz.lc with Trustwave SEG (v8, 2, 6, 11305) id ; Tue, 23 Mar 2021 17:33:48 +1300 Received: from chrisp-dl.ws.atlnz.lc (chrisp-dl.ws.atlnz.lc [10.33.22.20]) by smtp (Postfix) with ESMTP id E612813EED4; Tue, 23 Mar 2021 17:34:03 +1300 (NZDT) Received: by chrisp-dl.ws.atlnz.lc (Postfix, from userid 1030) id 64F0428409A; Tue, 23 Mar 2021 17:33:48 +1300 (NZDT) From: Chris Packham To: robh+dt@kernel.org, linux@roeck-us.net, wsa@kernel.org, jdelvare@suse.com Cc: linux-i2c@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Chris Packham Subject: [PATCH 5/6] i2c: mpc: use device managed APIs Date: Tue, 23 Mar 2021 17:33:30 +1300 Message-Id: <20210323043331.21878-6-chris.packham@alliedtelesis.co.nz> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210323043331.21878-1-chris.packham@alliedtelesis.co.nz> References: <20210323043331.21878-1-chris.packham@alliedtelesis.co.nz> MIME-Version: 1.0 X-SEG-SpamProfiler-Analysis: v=2.3 cv=GfppYjfL c=1 sm=1 tr=0 a=KLBiSEs5mFS1a/PbTCJxuA==:117 a=dESyimp9J3IA:10 a=X0Xs-PVj3CX0DAvrFM0A:9 X-SEG-SpamProfiler-Score: 0 x-atlnz-ls: pat Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org Use device managed functions an clean up error handling. Signed-off-by: Chris Packham --- drivers/i2c/busses/i2c-mpc.c | 46 ++++++++++++++---------------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 5b746a898e8e..46cdb36e2f9b 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -654,7 +654,6 @@ static int fsl_i2c_probe(struct platform_device *op) u32 clock = MPC_I2C_CLOCK_LEGACY; int result = 0; int plen; - struct resource res; struct clk *clk; int err; @@ -662,7 +661,7 @@ static int fsl_i2c_probe(struct platform_device *op) if (!match) return -EINVAL; - i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); + i2c = devm_kzalloc(&op->dev, sizeof(*i2c), GFP_KERNEL); if (!i2c) return -ENOMEM; @@ -670,24 +669,21 @@ static int fsl_i2c_probe(struct platform_device *op) init_waitqueue_head(&i2c->queue); - i2c->base = of_iomap(op->dev.of_node, 0); - if (!i2c->base) { + i2c->base = devm_platform_ioremap_resource(op, 0); + if (IS_ERR(i2c->base)) { dev_err(i2c->dev, "failed to map controller\n"); - result = -ENOMEM; - goto fail_map; + return PTR_ERR(i2c->base); } - i2c->irq = irq_of_parse_and_map(op->dev.of_node, 0); - if (i2c->irq < 0) { - result = i2c->irq; - goto fail_map; - } + i2c->irq = platform_get_irq(op, 0); + if (i2c->irq < 0) + return i2c->irq; - result = request_irq(i2c->irq, mpc_i2c_isr, + result = devm_request_irq(&op->dev, i2c->irq, mpc_i2c_isr, IRQF_SHARED, "i2c-mpc", i2c); if (result < 0) { dev_err(i2c->dev, "failed to attach interrupt\n"); - goto fail_request; + return result; } /* @@ -699,7 +695,7 @@ static int fsl_i2c_probe(struct platform_device *op) err = clk_prepare_enable(clk); if (err) { dev_err(&op->dev, "failed to enable clock\n"); - goto fail_request; + return err; } else { i2c->clk_per = clk; } @@ -731,32 +727,26 @@ static int fsl_i2c_probe(struct platform_device *op) } dev_info(i2c->dev, "timeout %u us\n", mpc_ops.timeout * 1000000 / HZ); - platform_set_drvdata(op, i2c); - i2c->adap = mpc_ops; - of_address_to_resource(op->dev.of_node, 0, &res); scnprintf(i2c->adap.name, sizeof(i2c->adap.name), - "MPC adapter at 0x%llx", (unsigned long long)res.start); - i2c_set_adapdata(&i2c->adap, i2c); + "MPC adapter (%s)", of_node_full_name(op->dev.of_node)); i2c->adap.dev.parent = &op->dev; + i2c->adap.nr = op->id; i2c->adap.dev.of_node = of_node_get(op->dev.of_node); i2c->adap.bus_recovery_info = &fsl_i2c_recovery_info; + platform_set_drvdata(op, i2c); + i2c_set_adapdata(&i2c->adap, i2c); - result = i2c_add_adapter(&i2c->adap); - if (result < 0) + result = i2c_add_numbered_adapter(&i2c->adap); + if (result) goto fail_add; - return result; + return 0; fail_add: if (i2c->clk_per) clk_disable_unprepare(i2c->clk_per); - free_irq(i2c->irq, i2c); - fail_request: - irq_dispose_mapping(i2c->irq); - iounmap(i2c->base); - fail_map: - kfree(i2c); + return result; }; From patchwork Tue Mar 23 04:33:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Packham X-Patchwork-Id: 407166 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 61290C433ED for ; Tue, 23 Mar 2021 04:34:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3808F619B6 for ; Tue, 23 Mar 2021 04:34:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229730AbhCWEe3 (ORCPT ); Tue, 23 Mar 2021 00:34:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33490 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229622AbhCWEdy (ORCPT ); Tue, 23 Mar 2021 00:33:54 -0400 Received: from gate2.alliedtelesis.co.nz (gate2.alliedtelesis.co.nz [IPv6:2001:df5:b000:5::4]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B212EC0613D9 for ; Mon, 22 Mar 2021 21:33:53 -0700 (PDT) Received: from svr-chch-seg1.atlnz.lc (mmarshal3.atlnz.lc [10.32.18.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by gate2.alliedtelesis.co.nz (Postfix) with ESMTPS id C25C6891B3; Tue, 23 Mar 2021 17:33:48 +1300 (NZDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alliedtelesis.co.nz; s=mail181024; t=1616474028; bh=QfeDP95sCv2SewuqWItI7gTMDloyQxHEwRRt8dG7Dr8=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=AJSeMcwxhs7CRawp/+BUuT4/Y/qrNRZ1EKeebnZhdLAP38SmEXAeV30xMzezpXw77 fCshKxpRywvJAAYJ+xlAi8pUHucGlPuyB0UbTujQcLNWlejkjFBO5w+A55uuA0u5Ao W1g/3dJkJbnue3Z4C5BKY/nJ6jL3MKJX1FrzJsScwrqCa9Hl+JLtRN9ws6week/uKu OdemY5p4Ctyk8SWCVl+CRck0WACkZgcahCWveZ7VrKJRMdLAg89Pc+pxYH+PpTOfOA poBhwLmAVx7twLLyR0DzjodjkUh2CWfdkEKFhMJmRIXnyphvtf7FnNOI+4goRJdZpl acAesl4Kck4sg== Received: from smtp (Not Verified[10.32.16.33]) by svr-chch-seg1.atlnz.lc with Trustwave SEG (v8, 2, 6, 11305) id ; Tue, 23 Mar 2021 17:33:48 +1300 Received: from chrisp-dl.ws.atlnz.lc (chrisp-dl.ws.atlnz.lc [10.33.22.20]) by smtp (Postfix) with ESMTP id 249B013EED4; Tue, 23 Mar 2021 17:34:04 +1300 (NZDT) Received: by chrisp-dl.ws.atlnz.lc (Postfix, from userid 1030) id 947B528409A; Tue, 23 Mar 2021 17:33:48 +1300 (NZDT) From: Chris Packham To: robh+dt@kernel.org, linux@roeck-us.net, wsa@kernel.org, jdelvare@suse.com Cc: linux-i2c@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Chris Packham Subject: [PATCH 6/6] i2c: mpc: Interrupt driven transfer Date: Tue, 23 Mar 2021 17:33:31 +1300 Message-Id: <20210323043331.21878-7-chris.packham@alliedtelesis.co.nz> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210323043331.21878-1-chris.packham@alliedtelesis.co.nz> References: <20210323043331.21878-1-chris.packham@alliedtelesis.co.nz> MIME-Version: 1.0 X-SEG-SpamProfiler-Analysis: v=2.3 cv=GfppYjfL c=1 sm=1 tr=0 a=KLBiSEs5mFS1a/PbTCJxuA==:117 a=dESyimp9J3IA:10 a=uHd7jcRfAAAA:8 a=5ev65v1id6XjEa6wf1UA:9 a=FVs-WqTgHo97eV9s:21 a=eDJpZUWDSCT-sJcP:21 a=W4h6EnClZ8UN7yAF:21 a=Ht9MEGjvesGdgnQqdPSO:22 X-SEG-SpamProfiler-Score: 0 x-atlnz-ls: pat Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org The fsl-i2c controller will generate an interrupt after every byte transferred. Make use of this interrupt to drive a state machine which allows the next part of a transfer to happen as soon as the interrupt is received. This is particularly helpful with SMBUS devices like the LM81 which will timeout if we take too long between bytes in a transfer. Signed-off-by: Chris Packham --- drivers/i2c/busses/i2c-mpc.c | 430 +++++++++++++++++++---------------- 1 file changed, 237 insertions(+), 193 deletions(-) diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 46cdb36e2f9b..5ffde3428232 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -1,16 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * (C) Copyright 2003-2004 - * Humboldt Solutions Ltd, adrian@humboldt.co.uk. - * This is a combined i2c adapter and algorithm driver for the * MPC107/Tsi107 PowerPC northbridge and processors that include * the same I2C unit (8240, 8245, 85xx). * - * Release 0.8 - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. + * Copyright (C) 2003-2004 Humboldt Solutions Ltd, adrian@humboldt.co.uk + * Copyright (C) 2021 Allied Telesis Labs */ #include @@ -58,11 +53,32 @@ #define CSR_MIF 0x02 #define CSR_RXAK 0x01 +enum mpc_i2c_action { + MPC_I2C_ACTION_INVALID = 0, + MPC_I2C_ACTION_START, + MPC_I2C_ACTION_RESTART, + MPC_I2C_ACTION_READ_BEGIN, + MPC_I2C_ACTION_READ_BYTE, + MPC_I2C_ACTION_WRITE, + MPC_I2C_ACTION_STOP, +}; + +static char *action_str[] = { + "invalid", + "start", + "restart", + "read begin", + "read", + "write", + "stop", +}; + struct mpc_i2c { struct device *dev; void __iomem *base; u32 interrupt; - wait_queue_head_t queue; + wait_queue_head_t waitq; + spinlock_t lock; struct i2c_adapter adap; int irq; u32 real_clk; @@ -70,6 +86,16 @@ struct mpc_i2c { u8 fdr, dfsrr; #endif struct clk *clk_per; + u32 cntl_bits; + enum mpc_i2c_action action; + struct i2c_msg *msgs; + int num_msgs; + int curr_msg; + u32 byte_posn; + u32 block; + int rc; + int expect_rxack; + }; struct mpc_i2c_divider { @@ -86,19 +112,6 @@ static inline void writeccr(struct mpc_i2c *i2c, u32 x) writeb(x, i2c->base + MPC_I2C_CR); } -static irqreturn_t mpc_i2c_isr(int irq, void *dev_id) -{ - struct mpc_i2c *i2c = dev_id; - if (readb(i2c->base + MPC_I2C_SR) & CSR_MIF) { - /* Read again to allow register to stabilise */ - i2c->interrupt = readb(i2c->base + MPC_I2C_SR); - writeb(0, i2c->base + MPC_I2C_SR); - wake_up(&i2c->queue); - return IRQ_HANDLED; - } - return IRQ_NONE; -} - /* Sometimes 9th clock pulse isn't generated, and slave doesn't release * the bus, because it wants to send ACK. * Following sequence of enabling/disabling and sending start/stop generates @@ -121,45 +134,6 @@ static void mpc_i2c_fixup(struct mpc_i2c *i2c) } } -static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) -{ - u32 cmd_err; - int result; - - result = wait_event_timeout(i2c->queue, - (i2c->interrupt & CSR_MIF), timeout); - - if (unlikely(!(i2c->interrupt & CSR_MIF))) { - dev_dbg(i2c->dev, "wait timeout\n"); - writeccr(i2c, 0); - result = -ETIMEDOUT; - } - - cmd_err = i2c->interrupt; - i2c->interrupt = 0; - - if (result < 0) - return result; - - if (!(cmd_err & CSR_MCF)) { - dev_dbg(i2c->dev, "unfinished\n"); - return -EIO; - } - - if (cmd_err & CSR_MAL) { - dev_dbg(i2c->dev, "MAL\n"); - return -EAGAIN; - } - - if (writing && (cmd_err & CSR_RXAK)) { - dev_dbg(i2c->dev, "No RXAK\n"); - /* generate stop */ - writeccr(i2c, CCR_MEN); - return -ENXIO; - } - return 0; -} - #if defined(CONFIG_PPC_MPC52xx) || defined(CONFIG_PPC_MPC512x) static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] = { {20, 0x20}, {22, 0x21}, {24, 0x22}, {26, 0x23}, @@ -434,168 +408,209 @@ static void mpc_i2c_setup_8xxx(struct device_node *node, } #endif /* CONFIG_FSL_SOC */ -static void mpc_i2c_start(struct mpc_i2c *i2c) +static void mpc_i2c_finish(struct mpc_i2c *i2c, int rc) { - /* Clear arbitration */ - writeb(0, i2c->base + MPC_I2C_SR); - /* Start with MEN */ - writeccr(i2c, CCR_MEN); + i2c->rc = rc; + i2c->block = 0; + i2c->cntl_bits = CCR_MEN; + writeccr(i2c, i2c->cntl_bits); + wake_up(&i2c->waitq); } -static void mpc_i2c_stop(struct mpc_i2c *i2c) +static void mpc_i2c_do_action(struct mpc_i2c *i2c) { - writeccr(i2c, CCR_MEN); -} + struct i2c_msg *msg = &i2c->msgs[i2c->curr_msg]; + int dir = 0; + int recv_len = 0; + u8 byte; + + dev_dbg(i2c->dev, "%s: action = %s\n", __func__, + action_str[i2c->action]); + + i2c->cntl_bits &= ~(CCR_RSTA | CCR_MTX | CCR_TXAK); + + if (msg->flags & I2C_M_RD) + dir = 1; + if (msg->flags & I2C_M_RECV_LEN) + recv_len = 1; + + switch (i2c->action) { + case MPC_I2C_ACTION_RESTART: + i2c->cntl_bits |= CCR_RSTA; + fallthrough; + + case MPC_I2C_ACTION_START: + i2c->cntl_bits |= CCR_MSTA | CCR_MTX; + writeccr(i2c, i2c->cntl_bits); + writeb((msg->addr << 1) | dir, i2c->base + MPC_I2C_DR); + i2c->expect_rxack = 1; + i2c->action = dir ? MPC_I2C_ACTION_READ_BEGIN : MPC_I2C_ACTION_WRITE; + break; + + case MPC_I2C_ACTION_READ_BEGIN: + if (msg->len) { + if (msg->len == 1 && !(msg->flags & I2C_M_RECV_LEN)) + i2c->cntl_bits |= CCR_TXAK; + + writeccr(i2c, i2c->cntl_bits); + /* Dummy read */ + readb(i2c->base + MPC_I2C_DR); + } + i2c->action = MPC_I2C_ACTION_READ_BYTE; + break; -static int mpc_write(struct mpc_i2c *i2c, int target, - const u8 *data, int length, int restart) -{ - int i, result; - unsigned timeout = i2c->adap.timeout; - u32 flags = restart ? CCR_RSTA : 0; + case MPC_I2C_ACTION_READ_BYTE: + if (i2c->byte_posn || !recv_len) { + /* Generate txack on next to last byte */ + if (i2c->byte_posn == msg->len - 2) + i2c->cntl_bits |= CCR_TXAK; + /* Do not generate stop on last byte */ + if (i2c->byte_posn == msg->len - 1) + i2c->cntl_bits |= CCR_MTX; - /* Start as master */ - writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags); - /* Write target byte */ - writeb((target << 1), i2c->base + MPC_I2C_DR); + writeccr(i2c, i2c->cntl_bits); + } - result = i2c_wait(i2c, timeout, 1); - if (result < 0) - return result; + byte = readb(i2c->base + MPC_I2C_DR); - for (i = 0; i < length; i++) { - /* Write data byte */ - writeb(data[i], i2c->base + MPC_I2C_DR); + if (i2c->byte_posn == 0 && recv_len) { + if (byte == 0 || byte > I2C_SMBUS_BLOCK_MAX) { + mpc_i2c_finish(i2c, -EPROTO); + return; + } + msg->len += byte; + /* + * For block reads, generate txack here if data length + * is 1 byte (total length is 2 bytes). + */ + if (msg->len == 2) { + i2c->cntl_bits |= CCR_TXAK; + writeccr(i2c, i2c->cntl_bits); + } + } - result = i2c_wait(i2c, timeout, 1); - if (result < 0) - return result; + dev_dbg(i2c->dev, "%s: %s %02x\n", __func__, + action_str[i2c->action], byte); + msg->buf[i2c->byte_posn++] = byte; + break; + + case MPC_I2C_ACTION_WRITE: + dev_dbg(i2c->dev, "%s: %s %02x\n", __func__, + action_str[i2c->action], msg->buf[i2c->byte_posn]); + writeb(msg->buf[i2c->byte_posn++], i2c->base + MPC_I2C_DR); + i2c->expect_rxack = 1; + break; + + case MPC_I2C_ACTION_STOP: + mpc_i2c_finish(i2c, 0); + break; + + case MPC_I2C_ACTION_INVALID: + default: + BUG(); + break; } - return 0; + if (msg->len == i2c->byte_posn) { + i2c->curr_msg++; + i2c->byte_posn = 0; + + if (i2c->curr_msg == i2c->num_msgs) { + i2c->action = MPC_I2C_ACTION_STOP; + /* + * We don't get another interrupt on read so + * finish the transfer now + */ + if (dir) + mpc_i2c_finish(i2c, 0); + } else { + i2c->action = MPC_I2C_ACTION_RESTART; + } + } } -static int mpc_read(struct mpc_i2c *i2c, int target, - u8 *data, int length, int restart, bool recv_len) +static void mpc_i2c_do_intr(struct mpc_i2c *i2c, u8 status) { - unsigned timeout = i2c->adap.timeout; - int i, result; - u32 flags = restart ? CCR_RSTA : 0; + unsigned long flags; - /* Switch to read - restart */ - writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags); - /* Write target address byte - this time with the read flag set */ - writeb((target << 1) | 1, i2c->base + MPC_I2C_DR); + spin_lock_irqsave(&i2c->lock, flags); - result = i2c_wait(i2c, timeout, 1); - if (result < 0) - return result; + if (!(status & CSR_MCF)) { + dev_dbg(i2c->dev, "unfinished\n"); + mpc_i2c_finish(i2c, -EIO); + goto out; + } - if (length) { - if (length == 1 && !recv_len) - writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK); - else - writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA); - /* Dummy read */ - readb(i2c->base + MPC_I2C_DR); + if (status & CSR_MAL) { + dev_dbg(i2c->dev, "arbiritration lost\n"); + mpc_i2c_finish(i2c, -EAGAIN); + goto out; } - for (i = 0; i < length; i++) { - u8 byte; + if (i2c->expect_rxack && (status & CSR_RXAK)) { + dev_dbg(i2c->dev, "no RXAK\n"); + mpc_i2c_finish(i2c, -ENXIO); + goto out; + } + i2c->expect_rxack = 0; - result = i2c_wait(i2c, timeout, 0); - if (result < 0) - return result; + mpc_i2c_do_action(i2c); - /* - * For block reads, we have to know the total length (1st byte) - * before we can determine if we are done. - */ - if (i || !recv_len) { - /* Generate txack on next to last byte */ - if (i == length - 2) - writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA - | CCR_TXAK); - /* Do not generate stop on last byte */ - if (i == length - 1) - writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA - | CCR_MTX); - } +out: + spin_unlock_irqrestore(&i2c->lock, flags); +} - byte = readb(i2c->base + MPC_I2C_DR); +static irqreturn_t mpc_i2c_isr(int irq, void *dev_id) +{ + struct mpc_i2c *i2c = dev_id; + u8 status = readb(i2c->base + MPC_I2C_SR); - /* - * Adjust length if first received byte is length. - * The length is 1 length byte plus actually data length - */ - if (i == 0 && recv_len) { - if (byte == 0 || byte > I2C_SMBUS_BLOCK_MAX) - return -EPROTO; - length += byte; - /* - * For block reads, generate txack here if data length - * is 1 byte (total length is 2 bytes). - */ - if (length == 2) - writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA - | CCR_TXAK); - } - data[i] = byte; + if (status & CSR_MIF) { + writeb(0, i2c->base + MPC_I2C_SR); + mpc_i2c_do_intr(i2c, status); + return IRQ_HANDLED; } + return IRQ_NONE; +} + +static void mpc_i2c_wait_for_completion(struct mpc_i2c *i2c) +{ + long time_left; - return length; + time_left = wait_event_timeout(i2c->waitq, !i2c->block, i2c->adap.timeout); + + if (!time_left) + i2c->rc = -ETIMEDOUT; + else if (time_left < 0) + i2c->rc = time_left; } -static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +static int mpc_i2c_execute_msg(struct mpc_i2c *i2c) { - struct i2c_msg *pmsg; - int i; - int ret = 0; - unsigned long orig_jiffies = jiffies; - struct mpc_i2c *i2c = i2c_get_adapdata(adap); + unsigned long orig_jiffies; + unsigned long flags; - mpc_i2c_start(i2c); + spin_lock_irqsave(&i2c->lock, flags); - /* Allow bus up to 1s to become not busy */ - while (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) { - if (signal_pending(current)) { - dev_dbg(i2c->dev, "Interrupted\n"); - writeccr(i2c, 0); - return -EINTR; - } - if (time_after(jiffies, orig_jiffies + HZ)) { - u8 status = readb(i2c->base + MPC_I2C_SR); + i2c->curr_msg = 0; + i2c->rc = 0; + i2c->byte_posn = 0; + i2c->block = 1; + i2c->action = MPC_I2C_ACTION_START; - dev_dbg(i2c->dev, "timeout\n"); - if ((status & (CSR_MCF | CSR_MBB | CSR_RXAK)) != 0) { - writeb(status & ~CSR_MAL, - i2c->base + MPC_I2C_SR); - i2c_recover_bus(&i2c->adap); - } - return -EIO; - } - schedule(); - } + i2c->cntl_bits = CCR_MEN | CCR_MIEN; + writeb(0, i2c->base + MPC_I2C_SR); + writeccr(i2c, i2c->cntl_bits); + + mpc_i2c_do_action(i2c); + + spin_unlock_irqrestore(&i2c->lock, flags); + + mpc_i2c_wait_for_completion(i2c); + + if (i2c->rc == -EIO || i2c->rc == -EAGAIN || i2c->rc == -ETIMEDOUT) + i2c_recover_bus(&i2c->adap); - for (i = 0; ret >= 0 && i < num; i++) { - pmsg = &msgs[i]; - dev_dbg(i2c->dev, - "Doing %s %d bytes to 0x%02x - %d of %d messages\n", - pmsg->flags & I2C_M_RD ? "read" : "write", - pmsg->len, pmsg->addr, i + 1, num); - if (pmsg->flags & I2C_M_RD) { - bool recv_len = pmsg->flags & I2C_M_RECV_LEN; - - ret = mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i, - recv_len); - if (recv_len && ret > 0) - pmsg->len = ret; - } else { - ret = - mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i); - } - } - mpc_i2c_stop(i2c); /* Initiate STOP */ orig_jiffies = jiffies; /* Wait until STOP is seen, allow up to 1 s */ while (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) { @@ -612,7 +627,35 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) } cond_resched(); } - return (ret < 0) ? ret : num; + + return i2c->rc; +} + +static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + int rc, ret = num; + struct mpc_i2c *i2c = i2c_get_adapdata(adap); + int i; + + dev_dbg(i2c->dev, "%s: num = %d\n", __func__, num); + for (i = 0; i < num; i++) + dev_dbg(i2c->dev, " addr = %02x, flags = %02x, len = %d, %*ph\n", + msgs[i].addr, msgs[i].flags, msgs[i].len, + msgs[i].flags & I2C_M_RD ? 0 : msgs[i].len, + msgs[i].buf); + + BUG_ON(i2c->msgs != NULL); + i2c->msgs = msgs; + i2c->num_msgs = num; + + rc = mpc_i2c_execute_msg(i2c); + if (rc < 0) + ret = rc; + + i2c->num_msgs = 0; + i2c->msgs = NULL; + + return ret; } static u32 mpc_functionality(struct i2c_adapter *adap) @@ -667,7 +710,8 @@ static int fsl_i2c_probe(struct platform_device *op) i2c->dev = &op->dev; /* for debug and error output */ - init_waitqueue_head(&i2c->queue); + init_waitqueue_head(&i2c->waitq); + spin_lock_init(&i2c->lock); i2c->base = devm_platform_ioremap_resource(op, 0); if (IS_ERR(i2c->base)) {