From patchwork Fri Mar 19 06:27:32 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455587 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=czl0aAnT; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=KuQYyQcv; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1v9y5Bblz9sVS for ; Fri, 19 Mar 2021 17:29:10 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233756AbhCSG2g (ORCPT ); Fri, 19 Mar 2021 02:28:36 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:33657 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233865AbhCSG21 (ORCPT ); Fri, 19 Mar 2021 02:28:27 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id 79132580A7A; Fri, 19 Mar 2021 02:28:26 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:28:26 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:mime-version :content-transfer-encoding; s=fm2; bh=jqgrbOeF372kIwTWjevU9VS3gs JIe6BCt8qh17+30Ws=; b=czl0aAnTucQqpeAVrdeq5zoo+NvsiSKJIfuWYluNjX 4wMSfY5kyD0CNy3WYxfz/5B/2MXU2H8AQFNSvMs4qNAnKrRg373jrIatUZCF+fD0 5O4YIgaJZK3RHljosZEtVr64Cv+iy/vPUzWUs+cptukE9PFSvNid5//zJWXmEzq7 IUuJwx1gRroCQ1dp/jPN3PcJvqLWoCtW8eajphloH2jBiKqWUaxRBG0N5qgQCSJ0 9ai8Pd1xpH9fUZ9gArRiwIuNiCHz8Jy/WBwrr6SClItH51NV03hhwg7mrKgnDHcI cOA+tuhHgwG9Xkix8zYE/vYuMaq8mp2dwWi7P7Zzs1NQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :message-id:mime-version:subject:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; bh=jqgrbOeF372kIwTWj evU9VS3gsJIe6BCt8qh17+30Ws=; b=KuQYyQcv39PKGIFYTELA8fxZA/QNd+P63 0bP++zjwu0ls12rrN/ioZqCyFG8kPy8luaPVc1P+eRygwizrd7B5HHXM/I6xPKJi YOaWYqik4hZH5KsQf6BpuGm7o6NXVLggPmxDkTej8pvhLnVLiy3hRX89jzMaWZ3n qSlHU+cR9z7KCFD3CyDUq98RKlZpYBr5YMftJ+K6AXI/zQxs3yUY/8+oShVj5u9i E/G83NaiLXwTDWMOwDjK6XxRcvyP5FJj7tiFA4fsabCryr9d3cykkAAYs6LWVUjS W9vYbZ3ClK+w4FckeP2Mm4gOn9tC5in3hxgX8QEuOPFabXTlQP7KQ== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffoggfgsedtkeertdertddtnecuhfhrohhmpeetnhgurhgvficu lfgvfhhfvghrhicuoegrnhgurhgvfiesrghjrdhiugdrrghuqeenucggtffrrghtthgvrh hnpeekhfeiffejveefveehtdeiiefhfedvjeelvddvtdehffetudejtefhueeuleeftden ucfkphepuddukedrvddutddrudekuddrheehnecuvehluhhsthgvrhfuihiivgeptdenuc frrghrrghmpehmrghilhhfrhhomheprghnughrvgifsegrjhdrihgurdgruh X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id B422E24005A; Fri, 19 Mar 2021 02:28:18 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, "Chia-Wei, Wang" , devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com, Rob Herring Subject: [PATCH v2 01/21] dt-bindings: aspeed-lpc: Remove LPC partitioning Date: Fri, 19 Mar 2021 16:57:32 +1030 Message-Id: <20210319062752.145730-1-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: "Chia-Wei, Wang" The LPC controller has no concept of the BMC and the Host partitions. This patch fixes the documentation by removing the description on LPC partitions. The register offsets illustrated in the DTS node examples are also fixed to adapt to the LPC DTS change. Signed-off-by: Chia-Wei Wang Reviewed-by: Andrew Jeffery Acked-by: Rob Herring Acked-by: Lee Jones Reviewed-by: Joel Stanley --- .../devicetree/bindings/mfd/aspeed-lpc.txt | 100 +++++------------- 1 file changed, 25 insertions(+), 75 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/aspeed-lpc.txt b/Documentation/devicetree/bindings/mfd/aspeed-lpc.txt index d0a38ba8b9ce..936aa108eab4 100644 --- a/Documentation/devicetree/bindings/mfd/aspeed-lpc.txt +++ b/Documentation/devicetree/bindings/mfd/aspeed-lpc.txt @@ -9,13 +9,7 @@ primary use case of the Aspeed LPC controller is as a slave on the bus conditions it can also take the role of bus master. The LPC controller is represented as a multi-function device to account for the -mix of functionality it provides. The principle split is between the register -layout at the start of the I/O space which is, to quote the Aspeed datasheet, -"basically compatible with the [LPC registers from the] popular BMC controller -H8S/2168[1]", and everything else, where everything else is an eclectic -collection of functions with a esoteric register layout. "Everything else", -here labeled the "host" portion of the controller, includes, but is not limited -to: +mix of functionality, which includes, but is not limited to: * An IPMI Block Transfer[2] Controller @@ -44,80 +38,36 @@ Required properties =================== - compatible: One of: - "aspeed,ast2400-lpc", "simple-mfd" - "aspeed,ast2500-lpc", "simple-mfd" - "aspeed,ast2600-lpc", "simple-mfd" + "aspeed,ast2400-lpc-v2", "simple-mfd", "syscon" + "aspeed,ast2500-lpc-v2", "simple-mfd", "syscon" + "aspeed,ast2600-lpc-v2", "simple-mfd", "syscon" - reg: contains the physical address and length values of the Aspeed LPC memory region. - #address-cells: <1> - #size-cells: <1> -- ranges: Maps 0 to the physical address and length of the LPC memory - region - -Required LPC Child nodes -======================== - -BMC Node --------- - -- compatible: One of: - "aspeed,ast2400-lpc-bmc" - "aspeed,ast2500-lpc-bmc" - "aspeed,ast2600-lpc-bmc" - -- reg: contains the physical address and length values of the - H8S/2168-compatible LPC controller memory region - -Host Node ---------- - -- compatible: One of: - "aspeed,ast2400-lpc-host", "simple-mfd", "syscon" - "aspeed,ast2500-lpc-host", "simple-mfd", "syscon" - "aspeed,ast2600-lpc-host", "simple-mfd", "syscon" - -- reg: contains the address and length values of the host-related - register space for the Aspeed LPC controller - -- #address-cells: <1> -- #size-cells: <1> -- ranges: Maps 0 to the address and length of the host-related LPC memory +- ranges: Maps 0 to the physical address and length of the LPC memory region Example: lpc: lpc@1e789000 { - compatible = "aspeed,ast2500-lpc", "simple-mfd"; + compatible = "aspeed,ast2500-lpc-v2", "simple-mfd", "syscon"; reg = <0x1e789000 0x1000>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0x1e789000 0x1000>; - lpc_bmc: lpc-bmc@0 { - compatible = "aspeed,ast2500-lpc-bmc"; + lpc_snoop: lpc-snoop@0 { + compatible = "aspeed,ast2600-lpc-snoop"; reg = <0x0 0x80>; - }; - - lpc_host: lpc-host@80 { - compatible = "aspeed,ast2500-lpc-host", "simple-mfd", "syscon"; - reg = <0x80 0x1e0>; - reg-io-width = <4>; - - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x80 0x1e0>; + interrupts = ; + snoop-ports = <0x80>; }; }; -BMC Node Children -================== - - -Host Node Children -================== LPC Host Interface Controller ------------------- @@ -149,14 +99,12 @@ Optional properties: Example: -lpc-host@80 { - lpc_ctrl: lpc-ctrl@0 { - compatible = "aspeed,ast2500-lpc-ctrl"; - reg = <0x0 0x80>; - clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - memory-region = <&flash_memory>; - flash = <&spi>; - }; +lpc_ctrl: lpc-ctrl@80 { + compatible = "aspeed,ast2500-lpc-ctrl"; + reg = <0x80 0x80>; + clocks = <&syscon ASPEED_CLK_GATE_LCLK>; + memory-region = <&flash_memory>; + flash = <&spi>; }; LPC Host Controller @@ -179,9 +127,9 @@ Required properties: Example: -lhc: lhc@20 { +lhc: lhc@a0 { compatible = "aspeed,ast2500-lhc"; - reg = <0x20 0x24 0x48 0x8>; + reg = <0xa0 0x24 0xc8 0x8>; }; LPC reset control @@ -192,16 +140,18 @@ state of the LPC bus. Some systems may chose to modify this configuration. Required properties: - - compatible: "aspeed,ast2600-lpc-reset" or - "aspeed,ast2500-lpc-reset" - "aspeed,ast2400-lpc-reset" + - compatible: One of: + "aspeed,ast2600-lpc-reset"; + "aspeed,ast2500-lpc-reset"; + "aspeed,ast2400-lpc-reset"; + - reg: offset and length of the IP in the LHC memory region - #reset-controller indicates the number of reset cells expected Example: -lpc_reset: reset-controller@18 { +lpc_reset: reset-controller@98 { compatible = "aspeed,ast2500-lpc-reset"; - reg = <0x18 0x4>; + reg = <0x98 0x4>; #reset-cells = <1>; }; From patchwork Fri Mar 19 06:27:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455588 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=M4xB4XoJ; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=piUHoLXx; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1v9z6LGQz9sWX for ; Fri, 19 Mar 2021 17:29:11 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233948AbhCSG2g (ORCPT ); Fri, 19 Mar 2021 02:28:36 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:41467 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233902AbhCSG2b (ORCPT ); Fri, 19 Mar 2021 02:28:31 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id 895DF580A7B; Fri, 19 Mar 2021 02:28:30 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:28:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=eAeeFPa/3aS0L UUJ3Y67rAstef4Oy7Z+U7b9/nIh0GQ=; b=M4xB4XoJiCL++vUJ99KH80XBrH4hC WlyyFJSgNHAWjwNJ4vyKpvnmX0ydndXoUv7JBe74K/zUxFHwwPbb+cWSHSr5y+Z5 0nKk6UE0De/kcyzbV43st9zp7pjXCBmIWdlBJtVFnPArPeL0WgzXuuUkUqoqK9+I scw/EOdLGf6SQ3iYZ9pYuydUfF+X8DOd7tR8XRU9oSrhdpBl+BADbQe6FCTbkODd dN74ZJSb27hGgq7G4w0tKqrbaOMmA2coPb+fTAyRahwFMzHgRKBiG3t3YaFt7LgL cZQJBiHbPOrPCdlR7pBrX8/df26vkTyeR8otPvvEVArLxZIvt4QQm8/QQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=eAeeFPa/3aS0LUUJ3Y67rAstef4Oy7Z+U7b9/nIh0GQ=; b=piUHoLXx DQgEWcCanDwsgpfRRukcbhbVWYyWRFpHUviUxg3rvK9zYs10Sxi0LiluSAia2CT5 h3CECGrCqsBKmkYy6N2WXvqhCw9w3C1c2u+3hmj4wPVzHLtV93vzKTcJlOqOcL0s eJH8/pNRm5hY/k7KIJkG7/wn5KxVEymRttB5GkCkKcVImz1YSE6XMV5z6NsUuLne OD3mP2GFByUaqNHPTmI/SvmXa25fnLuyWsy42UkBbnN6ohVUmGZBlScOVE32l58q 1ozQ8zLeYUEHLjWmI9k7mB/0p/FS68ukv5PhY0IbNc9G9L2t34jNlw4fzmclL0zq mVy6COGPWiZsog== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpeetnhgurhgv ficulfgvfhhfvghrhicuoegrnhgurhgvfiesrghjrdhiugdrrghuqeenucggtffrrghtth gvrhhnpeejgfdvveehteekveeggeellefgleetteejffelffdvudduveeiffegteelvefh teenucfkphepuddukedrvddutddrudekuddrheehnecuvehluhhsthgvrhfuihiivgeptd enucfrrghrrghmpehmrghilhhfrhhomheprghnughrvgifsegrjhdrihgurdgruh X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id F113624005D; Fri, 19 Mar 2021 02:28:24 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, "Chia-Wei, Wang" , devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 02/21] ARM: dts: Remove LPC BMC and Host partitions Date: Fri, 19 Mar 2021 16:57:33 +1030 Message-Id: <20210319062752.145730-2-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: "Chia-Wei, Wang" The LPC controller has no concept of the BMC and the Host partitions. A concrete instance is that the HICRB[5:4] are for the I/O port address configurtaion of KCS channel 1/2. However, the KCS driver cannot access HICRB for channel 1/2 initialization via syscon regmap interface due to the parition boundary. (i.e. offset 80h) In addition, for the HW design backward compatibility, a newly added HW control bit could be located at any reserved one over the LPC addressing space. Thereby, this patch removes the lpc-bmc and lpc-host child node and thus the LPC partitioning. Note that this change requires the synchronization between device tree change and the driver change. To prevent the misuse of old devicetrees with new drivers, or vice versa, the v2 compatible strings are adopted for the LPC device as listed: "aspeed,ast2400-lpc-v2" "aspeed,ast2500-lpc-v2" "aspeed,ast2600-lpc-v2" Signed-off-by: Chia-Wei Wang Reviewed-by: Andrew Jeffery --- arch/arm/boot/dts/aspeed-g4.dtsi | 70 +++++++----------- arch/arm/boot/dts/aspeed-g5.dtsi | 121 +++++++++++++----------------- arch/arm/boot/dts/aspeed-g6.dtsi | 123 +++++++++++++------------------ 3 files changed, 133 insertions(+), 181 deletions(-) diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi index e7a45ba18fc9..c5aeb3cf3a09 100644 --- a/arch/arm/boot/dts/aspeed-g4.dtsi +++ b/arch/arm/boot/dts/aspeed-g4.dtsi @@ -343,59 +343,45 @@ vuart: serial@1e787000 { }; lpc: lpc@1e789000 { - compatible = "aspeed,ast2400-lpc", "simple-mfd"; + compatible = "aspeed,ast2400-lpc-v2", "simple-mfd", "syscon"; reg = <0x1e789000 0x1000>; + reg-io-width = <4>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0x1e789000 0x1000>; - lpc_bmc: lpc-bmc@0 { - compatible = "aspeed,ast2400-lpc-bmc"; - reg = <0x0 0x80>; + lpc_ctrl: lpc-ctrl@80 { + compatible = "aspeed,ast2400-lpc-ctrl"; + reg = <0x80 0x10>; + clocks = <&syscon ASPEED_CLK_GATE_LCLK>; + status = "disabled"; }; - lpc_host: lpc-host@80 { - compatible = "aspeed,ast2400-lpc-host", "simple-mfd", "syscon"; - reg = <0x80 0x1e0>; - reg-io-width = <4>; - - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x80 0x1e0>; - - lpc_ctrl: lpc-ctrl@0 { - compatible = "aspeed,ast2400-lpc-ctrl"; - reg = <0x0 0x10>; - clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - status = "disabled"; - }; - - lpc_snoop: lpc-snoop@10 { - compatible = "aspeed,ast2400-lpc-snoop"; - reg = <0x10 0x8>; - interrupts = <8>; - clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - status = "disabled"; - }; + lpc_snoop: lpc-snoop@90 { + compatible = "aspeed,ast2400-lpc-snoop"; + reg = <0x90 0x8>; + interrupts = <8>; + clocks = <&syscon ASPEED_CLK_GATE_LCLK>; + status = "disabled"; + }; - lhc: lhc@20 { - compatible = "aspeed,ast2400-lhc"; - reg = <0x20 0x24 0x48 0x8>; - }; + lhc: lhc@a0 { + compatible = "aspeed,ast2400-lhc"; + reg = <0xa0 0x24 0xc8 0x8>; + }; - lpc_reset: reset-controller@18 { - compatible = "aspeed,ast2400-lpc-reset"; - reg = <0x18 0x4>; - #reset-cells = <1>; - }; + lpc_reset: reset-controller@98 { + compatible = "aspeed,ast2400-lpc-reset"; + reg = <0x98 0x4>; + #reset-cells = <1>; + }; - ibt: ibt@c0 { - compatible = "aspeed,ast2400-ibt-bmc"; - reg = <0xc0 0x18>; - interrupts = <8>; - status = "disabled"; - }; + ibt: ibt@140 { + compatible = "aspeed,ast2400-ibt-bmc"; + reg = <0x140 0x18>; + interrupts = <8>; + status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi index 21930521a986..d733c1f161c1 100644 --- a/arch/arm/boot/dts/aspeed-g5.dtsi +++ b/arch/arm/boot/dts/aspeed-g5.dtsi @@ -434,91 +434,74 @@ vuart: serial@1e787000 { }; lpc: lpc@1e789000 { - compatible = "aspeed,ast2500-lpc", "simple-mfd"; + compatible = "aspeed,ast2500-lpc-v2", "simple-mfd", "syscon"; reg = <0x1e789000 0x1000>; + reg-io-width = <4>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0x1e789000 0x1000>; - lpc_bmc: lpc-bmc@0 { - compatible = "aspeed,ast2500-lpc-bmc", "simple-mfd", "syscon"; - reg = <0x0 0x80>; - reg-io-width = <4>; - - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x0 0x80>; - - kcs1: kcs@24 { - compatible = "aspeed,ast2500-kcs-bmc-v2"; - reg = <0x24 0x1>, <0x30 0x1>, <0x3c 0x1>; - interrupts = <8>; - status = "disabled"; - }; - kcs2: kcs@28 { - compatible = "aspeed,ast2500-kcs-bmc-v2"; - reg = <0x28 0x1>, <0x34 0x1>, <0x40 0x1>; - interrupts = <8>; - status = "disabled"; - }; - kcs3: kcs@2c { - compatible = "aspeed,ast2500-kcs-bmc-v2"; - reg = <0x2c 0x1>, <0x38 0x1>, <0x44 0x1>; - interrupts = <8>; - status = "disabled"; - }; + kcs1: kcs@24 { + compatible = "aspeed,ast2500-kcs-bmc-v2"; + reg = <0x24 0x1>, <0x30 0x1>, <0x3c 0x1>; + interrupts = <8>; + status = "disabled"; }; - lpc_host: lpc-host@80 { - compatible = "aspeed,ast2500-lpc-host", "simple-mfd", "syscon"; - reg = <0x80 0x1e0>; - reg-io-width = <4>; + kcs2: kcs@28 { + compatible = "aspeed,ast2500-kcs-bmc-v2"; + reg = <0x28 0x1>, <0x34 0x1>, <0x40 0x1>; + interrupts = <8>; + status = "disabled"; + }; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x80 0x1e0>; + kcs3: kcs@2c { + compatible = "aspeed,ast2500-kcs-bmc-v2"; + reg = <0x2c 0x1>, <0x38 0x1>, <0x44 0x1>; + interrupts = <8>; + status = "disabled"; + }; - kcs4: kcs@94 { - compatible = "aspeed,ast2500-kcs-bmc-v2"; - reg = <0x94 0x1>, <0x98 0x1>, <0x9c 0x1>; - interrupts = <8>; - status = "disabled"; - }; + kcs4: kcs@114 { + compatible = "aspeed,ast2500-kcs-bmc-v2"; + reg = <0x114 0x1>, <0x118 0x1>, <0x11c 0x1>; + interrupts = <8>; + status = "disabled"; + }; - lpc_ctrl: lpc-ctrl@0 { - compatible = "aspeed,ast2500-lpc-ctrl"; - reg = <0x0 0x10>; - clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - status = "disabled"; - }; + lpc_ctrl: lpc-ctrl@80 { + compatible = "aspeed,ast2500-lpc-ctrl"; + reg = <0x80 0x10>; + clocks = <&syscon ASPEED_CLK_GATE_LCLK>; + status = "disabled"; + }; - lpc_snoop: lpc-snoop@10 { - compatible = "aspeed,ast2500-lpc-snoop"; - reg = <0x10 0x8>; - interrupts = <8>; - clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - status = "disabled"; - }; + lpc_snoop: lpc-snoop@90 { + compatible = "aspeed,ast2500-lpc-snoop"; + reg = <0x90 0x8>; + interrupts = <8>; + clocks = <&syscon ASPEED_CLK_GATE_LCLK>; + status = "disabled"; + }; - lpc_reset: reset-controller@18 { - compatible = "aspeed,ast2500-lpc-reset"; - reg = <0x18 0x4>; - #reset-cells = <1>; - }; + lpc_reset: reset-controller@98 { + compatible = "aspeed,ast2500-lpc-reset"; + reg = <0x98 0x4>; + #reset-cells = <1>; + }; - lhc: lhc@20 { - compatible = "aspeed,ast2500-lhc"; - reg = <0x20 0x24 0x48 0x8>; - }; + lhc: lhc@a0 { + compatible = "aspeed,ast2500-lhc"; + reg = <0xa0 0x24 0xc8 0x8>; + }; - ibt: ibt@c0 { - compatible = "aspeed,ast2500-ibt-bmc"; - reg = <0xc0 0x18>; - interrupts = <8>; - status = "disabled"; - }; + ibt: ibt@140 { + compatible = "aspeed,ast2500-ibt-bmc"; + reg = <0x140 0x18>; + interrupts = <8>; + status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi index 3ee470c2b7b5..f96607b7b4e2 100644 --- a/arch/arm/boot/dts/aspeed-g6.dtsi +++ b/arch/arm/boot/dts/aspeed-g6.dtsi @@ -460,91 +460,74 @@ wdt4: watchdog@1e7850c0 { }; lpc: lpc@1e789000 { - compatible = "aspeed,ast2600-lpc", "simple-mfd"; + compatible = "aspeed,ast2600-lpc-v2", "simple-mfd", "syscon"; reg = <0x1e789000 0x1000>; + reg-io-width = <4>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0x1e789000 0x1000>; - lpc_bmc: lpc-bmc@0 { - compatible = "aspeed,ast2600-lpc-bmc", "simple-mfd", "syscon"; - reg = <0x0 0x80>; - reg-io-width = <4>; - - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x0 0x80>; - - kcs1: kcs@24 { - compatible = "aspeed,ast2500-kcs-bmc-v2"; - reg = <0x24 0x1>, <0x30 0x1>, <0x3c 0x1>; - interrupts = ; - kcs_chan = <1>; - status = "disabled"; - }; - kcs2: kcs@28 { - compatible = "aspeed,ast2500-kcs-bmc-v2"; - reg = <0x28 0x1>, <0x34 0x1>, <0x40 0x1>; - interrupts = ; - status = "disabled"; - }; - kcs3: kcs@2c { - compatible = "aspeed,ast2500-kcs-bmc-v2"; - reg = <0x2c 0x1>, <0x38 0x1>, <0x44 0x1>; - interrupts = ; - status = "disabled"; - }; + kcs1: kcs@24 { + compatible = "aspeed,ast2500-kcs-bmc-v2"; + reg = <0x24 0x1>, <0x30 0x1>, <0x3c 0x1>; + interrupts = ; + kcs_chan = <1>; + status = "disabled"; }; - lpc_host: lpc-host@80 { - compatible = "aspeed,ast2600-lpc-host", "simple-mfd", "syscon"; - reg = <0x80 0x1e0>; - reg-io-width = <4>; + kcs2: kcs@28 { + compatible = "aspeed,ast2500-kcs-bmc-v2"; + reg = <0x28 0x1>, <0x34 0x1>, <0x40 0x1>; + interrupts = ; + status = "disabled"; + }; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x80 0x1e0>; + kcs3: kcs@2c { + compatible = "aspeed,ast2500-kcs-bmc-v2"; + reg = <0x2c 0x1>, <0x38 0x1>, <0x44 0x1>; + interrupts = ; + status = "disabled"; + }; - kcs4: kcs@94 { - compatible = "aspeed,ast2500-kcs-bmc-v2"; - reg = <0x94 0x1>, <0x98 0x1>, <0x9c 0x1>; - interrupts = ; - status = "disabled"; - }; + kcs4: kcs@114 { + compatible = "aspeed,ast2500-kcs-bmc-v2"; + reg = <0x114 0x1>, <0x118 0x1>, <0x11c 0x1>; + interrupts = ; + status = "disabled"; + }; - lpc_ctrl: lpc-ctrl@0 { - compatible = "aspeed,ast2600-lpc-ctrl"; - reg = <0x0 0x80>; - clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - status = "disabled"; - }; + lpc_ctrl: lpc-ctrl@80 { + compatible = "aspeed,ast2600-lpc-ctrl"; + reg = <0x80 0x80>; + clocks = <&syscon ASPEED_CLK_GATE_LCLK>; + status = "disabled"; + }; - lpc_snoop: lpc-snoop@0 { - compatible = "aspeed,ast2600-lpc-snoop"; - reg = <0x0 0x80>; - interrupts = ; - clocks = <&syscon ASPEED_CLK_GATE_LCLK>; - status = "disabled"; - }; + lpc_snoop: lpc-snoop@80 { + compatible = "aspeed,ast2600-lpc-snoop"; + reg = <0x80 0x80>; + interrupts = ; + clocks = <&syscon ASPEED_CLK_GATE_LCLK>; + status = "disabled"; + }; - lhc: lhc@20 { - compatible = "aspeed,ast2600-lhc"; - reg = <0x20 0x24 0x48 0x8>; - }; + lhc: lhc@a0 { + compatible = "aspeed,ast2600-lhc"; + reg = <0xa0 0x24 0xc8 0x8>; + }; - lpc_reset: reset-controller@18 { - compatible = "aspeed,ast2600-lpc-reset"; - reg = <0x18 0x4>; - #reset-cells = <1>; - }; + lpc_reset: reset-controller@98 { + compatible = "aspeed,ast2600-lpc-reset"; + reg = <0x98 0x4>; + #reset-cells = <1>; + }; - ibt: ibt@c0 { - compatible = "aspeed,ast2600-ibt-bmc"; - reg = <0xc0 0x18>; - interrupts = ; - status = "disabled"; - }; + ibt: ibt@140 { + compatible = "aspeed,ast2600-ibt-bmc"; + reg = <0x140 0x18>; + interrupts = ; + status = "disabled"; }; }; From patchwork Fri Mar 19 06:27:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455593 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=OCmJLCs4; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=LqTz8BGA; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vBY4JkKz9sVS for ; Fri, 19 Mar 2021 17:29:41 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233963AbhCSG3K (ORCPT ); Fri, 19 Mar 2021 02:29:10 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:41521 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233957AbhCSG2h (ORCPT ); Fri, 19 Mar 2021 02:28:37 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id 0E7FB580A7C; Fri, 19 Mar 2021 02:28:37 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:28:37 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=3rglRCF2+66zH KVRZ4boDJXOEtO8m9hvabADBH87BCQ=; b=OCmJLCs4g7q1/uXGIYjxhtHRAMwpJ MDuR7EJpwmYZPttmVjsipap02dNAwYtDVS3ji9A5IETgNYLJ397OcoRUiEcKix1s cJJbILPpuEpcQWmLPslWgV6/uQK5N4Tt8vr/XgeZ/RNKkUadcEmzEAVVCmY31KMu I0lJ2qfhcjrktRAhUK/v9Pm4DAZErB637f7Mwn8XaEe/Cf326Aw3uoGx+kN8jqfv OAtbpXJrQMUvp4a5xNQLRf3yiw0bibq1uicW5iVBM117P0lUhf1T+6xWVyyqEbO9 bWvVxZndmZCXXTegYtfPXY4hxnO5PeTnofT8Vx7ouxg+LYJ1JELWyHL3w== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=3rglRCF2+66zHKVRZ4boDJXOEtO8m9hvabADBH87BCQ=; b=LqTz8BGA hDUGtrL4/ajCM3j9kl665R82qFQnrLOiRQVVRBk1KhD5uleW8s9+Zzf3Rsb15H5e AaIel1xvJDtYN3nc0RtdVgdPHpyBTx8ZTdV3E3YFMBISDyJr936YfPUo6/JAYxb5 PxVb+mWvzZL1RTOyaccqnFaKxuqa1j2qQpCgbXshYnnTgXZ44H15iQHz7Xhlhc3e Vs8SAJlZDOeR6L4/3oFUc9rZs5xFgtf2zBHFSCf7KJBoz47zh7YNyp7a5HwRMvSR pjpT+0VVxUZKgOMN1ocEFVVwGanYamLbk/miJWshO48Og25FIIrd9P98xradh+F4 RQU5QgDF4TgOqw== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpeetnhgurhgv ficulfgvfhhfvghrhicuoegrnhgurhgvfiesrghjrdhiugdrrghuqeenucggtffrrghtth gvrhhnpeejgfdvveehteekveeggeellefgleetteejffelffdvudduveeiffegteelvefh teenucfkphepuddukedrvddutddrudekuddrheehnecuvehluhhsthgvrhfuihiivgepud enucfrrghrrghmpehmrghilhhfrhhomheprghnughrvgifsegrjhdrihgurdgruh X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id EC605240054; Fri, 19 Mar 2021 02:28:30 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, "Chia-Wei, Wang" , devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com, Haiyue Wang Subject: [PATCH v2 03/21] ipmi: kcs: aspeed: Adapt to new LPC DTS layout Date: Fri, 19 Mar 2021 16:57:34 +1030 Message-Id: <20210319062752.145730-3-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: "Chia-Wei, Wang" Add check against LPC device v2 compatible string to ensure that the fixed device tree layout is adopted. The LPC register offsets are also fixed accordingly. Signed-off-by: Chia-Wei Wang Reviewed-by: Andrew Jeffery Acked-by: Haiyue Wang Reviewed-by: Joel Stanley --- drivers/char/ipmi/kcs_bmc_aspeed.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index a140203c079b..eefe362f65f0 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -27,7 +27,6 @@ #define KCS_CHANNEL_MAX 4 -/* mapped to lpc-bmc@0 IO space */ #define LPC_HICR0 0x000 #define LPC_HICR0_LPC3E BIT(7) #define LPC_HICR0_LPC2E BIT(6) @@ -52,15 +51,13 @@ #define LPC_STR1 0x03C #define LPC_STR2 0x040 #define LPC_STR3 0x044 - -/* mapped to lpc-host@80 IO space */ -#define LPC_HICRB 0x080 +#define LPC_HICRB 0x100 #define LPC_HICRB_IBFIF4 BIT(1) #define LPC_HICRB_LPC4E BIT(0) -#define LPC_LADR4 0x090 -#define LPC_IDR4 0x094 -#define LPC_ODR4 0x098 -#define LPC_STR4 0x09C +#define LPC_LADR4 0x110 +#define LPC_IDR4 0x114 +#define LPC_ODR4 0x118 +#define LPC_STR4 0x11C struct aspeed_kcs_bmc { struct regmap *map; @@ -348,12 +345,20 @@ static int aspeed_kcs_probe(struct platform_device *pdev) struct device_node *np; int rc; - np = pdev->dev.of_node; + np = dev->of_node->parent; + if (!of_device_is_compatible(np, "aspeed,ast2400-lpc-v2") && + !of_device_is_compatible(np, "aspeed,ast2500-lpc-v2") && + !of_device_is_compatible(np, "aspeed,ast2600-lpc-v2")) { + dev_err(dev, "unsupported LPC device binding\n"); + return -ENODEV; + } + + np = dev->of_node; if (of_device_is_compatible(np, "aspeed,ast2400-kcs-bmc") || - of_device_is_compatible(np, "aspeed,ast2500-kcs-bmc")) + of_device_is_compatible(np, "aspeed,ast2500-kcs-bmc")) kcs_bmc = aspeed_kcs_probe_of_v1(pdev); else if (of_device_is_compatible(np, "aspeed,ast2400-kcs-bmc-v2") || - of_device_is_compatible(np, "aspeed,ast2500-kcs-bmc-v2")) + of_device_is_compatible(np, "aspeed,ast2500-kcs-bmc-v2")) kcs_bmc = aspeed_kcs_probe_of_v2(pdev); else return -EINVAL; From patchwork Fri Mar 19 06:27:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455594 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=hODnRte/; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=jWpyY1GC; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vBb18GMz9sWF for ; Fri, 19 Mar 2021 17:29:43 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234040AbhCSG3K (ORCPT ); Fri, 19 Mar 2021 02:29:10 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:55211 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233937AbhCSG2n (ORCPT ); Fri, 19 Mar 2021 02:28:43 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id C1F40580A7F; Fri, 19 Mar 2021 02:28:42 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:28:42 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=sic3qYlOCrq3L +pvEQYeldSvAa2Qy+Xy8lgLaF/EF40=; b=hODnRte/FtT1Aaf25m+nUpIsfLOmq E2bOshf1RD+Trr8qtHai6iDdVPuW7zrzuzHHlg9nNbAZlBdYiPVbshOFMSLIp+8q NmfqJ42/HFi+eMBC62U5XOWqFV1MUKX5TzEytDNP5gMduhXnjuwtq7HpxFbtTG4l SPcsCJorPa0cPgAYrSdWph0rz+yclBaCZ5eAwbv/838XKITSUFhE21W9CyXqyknm +MFkL76NTghRogIVKEjAzUlrHlWInB1RROymNdgXg1u9cnPf6tfNmGjkS+N1IDdI iF+S4CEAVxw2D433EvA0ZECL4H4v84MRVquQyImJ4jMZkSJzWqm+rmwkg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=sic3qYlOCrq3L+pvEQYeldSvAa2Qy+Xy8lgLaF/EF40=; b=jWpyY1GC mffDjfEx9SJn4iKY3jQDrqEq9y9dGlgfQrzBQM+sohwMnweR+7e47e3B8Rx90+JS Erwm5BSONeYAAk12IxKsgRFVFSwgX3NJVgWBhs7alXB2TF832R81DPTvaWFVe4VW SJ2DETmEDM7pU31vur+PW3t2KnsBiNY0uShBu/boWy2cYUtosT94V8H02peakQQC nEAPcVekVqp+If4guezmhbkD3+pUbwAZSIWqQeud67Gh78+ZiPDAAsPuFhjSaEUd rYxz+ipAvCwl40RKsbX11TPVsGSJobqyKeI85xXztOr4/7SFxq80JVfc49+UHjFK p5iSy3NBG1c8Mw== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpeetnhgurhgv ficulfgvfhhfvghrhicuoegrnhgurhgvfiesrghjrdhiugdrrghuqeenucggtffrrghtth gvrhhnpeejgfdvveehteekveeggeellefgleetteejffelffdvudduveeiffegteelvefh teenucfkphepuddukedrvddutddrudekuddrheehnecuvehluhhsthgvrhfuihiivgepvd enucfrrghrrghmpehmrghilhhfrhhomheprghnughrvgifsegrjhdrihgurdgruh X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 35E67240054; Fri, 19 Mar 2021 02:28:36 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, "Chia-Wei, Wang" , devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 04/21] pinctrl: aspeed-g5: Adapt to new LPC device tree layout Date: Fri, 19 Mar 2021 16:57:35 +1030 Message-Id: <20210319062752.145730-4-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: "Chia-Wei, Wang" Add check against LPC device v2 compatible string to ensure that the fixed device tree layout is adopted. The LPC register offsets are also fixed accordingly. Signed-off-by: Chia-Wei Wang Reviewed-by: Andrew Jeffery Acked-by: Linus Walleij Reviewed-by: Joel Stanley --- drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c index 0cab4c2576e2..996ebcba4d38 100644 --- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c @@ -60,7 +60,7 @@ #define COND2 { ASPEED_IP_SCU, SCU94, GENMASK(1, 0), 0, 0 } /* LHCR0 is offset from the end of the H8S/2168-compatible registers */ -#define LHCR0 0x20 +#define LHCR0 0xa0 #define GFX064 0x64 #define B14 0 @@ -2648,14 +2648,19 @@ static struct regmap *aspeed_g5_acquire_regmap(struct aspeed_pinmux_data *ctx, } if (ip == ASPEED_IP_LPC) { - struct device_node *node; + struct device_node *np; struct regmap *map; - node = of_parse_phandle(ctx->dev->of_node, + np = of_parse_phandle(ctx->dev->of_node, "aspeed,external-nodes", 1); - if (node) { - map = syscon_node_to_regmap(node->parent); - of_node_put(node); + if (np) { + if (!of_device_is_compatible(np->parent, "aspeed,ast2400-lpc-v2") && + !of_device_is_compatible(np->parent, "aspeed,ast2500-lpc-v2") && + !of_device_is_compatible(np->parent, "aspeed,ast2600-lpc-v2")) + return ERR_PTR(-ENODEV); + + map = syscon_node_to_regmap(np->parent); + of_node_put(np); if (IS_ERR(map)) return map; } else From patchwork Fri Mar 19 06:27:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455595 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=bmx//uyg; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=j73iwh1P; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vBb4mPTz9sWP for ; Fri, 19 Mar 2021 17:29:43 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234043AbhCSG3L (ORCPT ); Fri, 19 Mar 2021 02:29:11 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:46915 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234032AbhCSG2t (ORCPT ); Fri, 19 Mar 2021 02:28:49 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id C1BFB580A7A; Fri, 19 Mar 2021 02:28:48 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:28:48 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=jXk9X+CpMGc9m 2udSUAL4q3h08wm/yg9nEbrKHZ03A8=; b=bmx//uygFN4zHRjJ5Zr03MlO2eTtk 9EmHFtxEBjdMW4pY6QJXaWtAfulM/ErlpAO8XKshGvlz82zROxsPQthpH3TtwJbR gVefHJWTwN8cxhO2A2U446rqTwm+D/fCt5LuA4loQtJEbrzkxZLiom0oUOcJXiej G7Ojy4De9Em1jbZe+B19nONuxybUTix4hOyffBoyHmg8wE7EgYFqBJZ5n1gyA125 shl7XFu6n/dmCcYZxFCF5/bn1MFRA3Sg5xNvQkbON9LPP6cZvNJDdlgCEorsDS4v iay6saGpoRIy610XYnccVRI00X129J77qK4AmXmkY3Nd9uGLVeb+fk2lw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=jXk9X+CpMGc9m2udSUAL4q3h08wm/yg9nEbrKHZ03A8=; b=j73iwh1P hSxlkrMqS4TDwnru5fwJOE5SGfBI+mqm5RVA7lu3Apu+4BHhqBEE61YoEUvjSA+z rc5ELZb61vP/wHHOiEq1UiCI3tOkOknHFlaqKs4MkrXUzhGJJGxKYvDzIOck9zrn K11mCrWsjzxSW3k8AtDYqWHxB9z1G0mBAmI22FM5M8OlGahR/GSLofBqNv3jD6fX b4bTaD1lEasydFlAurNwxy726hDXYRvNmXY/VyPLGuSXpED7o79uPYpYp4dY5Y1y SkKtiogwCamge/0ILgqlCI4KVJPad7HTwmZRG2m35EC4OU8tULTyZHOt6Rih6FLv 2zKfwqDbmKr0tA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpeetnhgurhgv ficulfgvfhhfvghrhicuoegrnhgurhgvfiesrghjrdhiugdrrghuqeenucggtffrrghtth gvrhhnpeejgfdvveehteekveeggeellefgleetteejffelffdvudduveeiffegteelvefh teenucfkphepuddukedrvddutddrudekuddrheehnecuvehluhhsthgvrhfuihiivgepfe enucfrrghrrghmpehmrghilhhfrhhomheprghnughrvgifsegrjhdrihgurdgruh X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 31253240054; Fri, 19 Mar 2021 02:28:42 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, "Chia-Wei, Wang" , devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 05/21] soc: aspeed: Adapt to new LPC device tree layout Date: Fri, 19 Mar 2021 16:57:36 +1030 Message-Id: <20210319062752.145730-5-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org From: "Chia-Wei, Wang" Add check against LPC device v2 compatible string to ensure that the fixed device tree layout is adopted. The LPC register offsets are also fixed accordingly. Signed-off-by: Chia-Wei Wang Reviewed-by: Andrew Jeffery Reviewed-by: Joel Stanley --- drivers/soc/aspeed/aspeed-lpc-ctrl.c | 20 ++++++++++++++------ drivers/soc/aspeed/aspeed-lpc-snoop.c | 23 +++++++++++++++-------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/drivers/soc/aspeed/aspeed-lpc-ctrl.c b/drivers/soc/aspeed/aspeed-lpc-ctrl.c index 439bcd6b8c4a..c557ffd0992c 100644 --- a/drivers/soc/aspeed/aspeed-lpc-ctrl.c +++ b/drivers/soc/aspeed/aspeed-lpc-ctrl.c @@ -18,15 +18,15 @@ #define DEVICE_NAME "aspeed-lpc-ctrl" -#define HICR5 0x0 +#define HICR5 0x80 #define HICR5_ENL2H BIT(8) #define HICR5_ENFWH BIT(10) -#define HICR6 0x4 +#define HICR6 0x84 #define SW_FWH2AHB BIT(17) -#define HICR7 0x8 -#define HICR8 0xc +#define HICR7 0x88 +#define HICR8 0x8c struct aspeed_lpc_ctrl { struct miscdevice miscdev; @@ -215,6 +215,7 @@ static int aspeed_lpc_ctrl_probe(struct platform_device *pdev) struct device_node *node; struct resource resm; struct device *dev; + struct device_node *np; int rc; dev = &pdev->dev; @@ -270,8 +271,15 @@ static int aspeed_lpc_ctrl_probe(struct platform_device *pdev) } } - lpc_ctrl->regmap = syscon_node_to_regmap( - pdev->dev.parent->of_node); + np = pdev->dev.parent->of_node; + if (!of_device_is_compatible(np, "aspeed,ast2400-lpc-v2") && + !of_device_is_compatible(np, "aspeed,ast2500-lpc-v2") && + !of_device_is_compatible(np, "aspeed,ast2600-lpc-v2")) { + dev_err(dev, "unsupported LPC device binding\n"); + return -ENODEV; + } + + lpc_ctrl->regmap = syscon_node_to_regmap(np); if (IS_ERR(lpc_ctrl->regmap)) { dev_err(dev, "Couldn't get regmap\n"); return -ENODEV; diff --git a/drivers/soc/aspeed/aspeed-lpc-snoop.c b/drivers/soc/aspeed/aspeed-lpc-snoop.c index 20acac6342ef..210455efb321 100644 --- a/drivers/soc/aspeed/aspeed-lpc-snoop.c +++ b/drivers/soc/aspeed/aspeed-lpc-snoop.c @@ -29,26 +29,25 @@ #define NUM_SNOOP_CHANNELS 2 #define SNOOP_FIFO_SIZE 2048 -#define HICR5 0x0 +#define HICR5 0x80 #define HICR5_EN_SNP0W BIT(0) #define HICR5_ENINT_SNP0W BIT(1) #define HICR5_EN_SNP1W BIT(2) #define HICR5_ENINT_SNP1W BIT(3) - -#define HICR6 0x4 +#define HICR6 0x84 #define HICR6_STR_SNP0W BIT(0) #define HICR6_STR_SNP1W BIT(1) -#define SNPWADR 0x10 +#define SNPWADR 0x90 #define SNPWADR_CH0_MASK GENMASK(15, 0) #define SNPWADR_CH0_SHIFT 0 #define SNPWADR_CH1_MASK GENMASK(31, 16) #define SNPWADR_CH1_SHIFT 16 -#define SNPWDR 0x14 +#define SNPWDR 0x94 #define SNPWDR_CH0_MASK GENMASK(7, 0) #define SNPWDR_CH0_SHIFT 0 #define SNPWDR_CH1_MASK GENMASK(15, 8) #define SNPWDR_CH1_SHIFT 8 -#define HICRB 0x80 +#define HICRB 0x100 #define HICRB_ENSNP0D BIT(14) #define HICRB_ENSNP1D BIT(15) @@ -260,6 +259,7 @@ static int aspeed_lpc_snoop_probe(struct platform_device *pdev) { struct aspeed_lpc_snoop *lpc_snoop; struct device *dev; + struct device_node *np; u32 port; int rc; @@ -269,8 +269,15 @@ static int aspeed_lpc_snoop_probe(struct platform_device *pdev) if (!lpc_snoop) return -ENOMEM; - lpc_snoop->regmap = syscon_node_to_regmap( - pdev->dev.parent->of_node); + np = pdev->dev.parent->of_node; + if (!of_device_is_compatible(np, "aspeed,ast2400-lpc-v2") && + !of_device_is_compatible(np, "aspeed,ast2500-lpc-v2") && + !of_device_is_compatible(np, "aspeed,ast2600-lpc-v2")) { + dev_err(dev, "unsupported LPC device binding\n"); + return -ENODEV; + } + + lpc_snoop->regmap = syscon_node_to_regmap(np); if (IS_ERR(lpc_snoop->regmap)) { dev_err(dev, "Couldn't get regmap\n"); return -ENODEV; From patchwork Fri Mar 19 06:27:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455596 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=cHzx2hl0; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=WuAyjie2; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vBc4ZrGz9sVS for ; Fri, 19 Mar 2021 17:29:44 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234050AbhCSG3N (ORCPT ); Fri, 19 Mar 2021 02:29:13 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:35997 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233828AbhCSG2z (ORCPT ); Fri, 19 Mar 2021 02:28:55 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id B93FB580A7B; Fri, 19 Mar 2021 02:28:54 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:28:54 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=Wz3rX2JLSP5Um Nsodg+6xxFvrCs/exUmWb2IW/KKfH8=; b=cHzx2hl0tLsTSvPyl9/UXEPRRPcFk yuY09IrTbQHscFSX3y8ZZn7qHWy9vha28nlV303U3XwOntUfsQ8+zfgT/jXQdSl2 U+u8j6998vK+OHZpPn7sAG5KIGYHOIadnxprpifF2AGWzNxmfRyhDWWBaNdQBTI4 lFxuXomzz4H0dwsj1ccKZ/Ivh7LwznjhjIvPVEHNRqZI1dJ5DPzYrh9Zk1QzJqIb QM3iYQT6Aas+vB14Ndj4w891JMn55/r+jcDG4qOmavC8OeTpu1An56gHcqXiB479 nQqZkj8+ii/amMHQtYYmJIKQXeFVh3cfnCkfR94Y/uGFHjnq7acYQAg2Q== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=Wz3rX2JLSP5UmNsodg+6xxFvrCs/exUmWb2IW/KKfH8=; b=WuAyjie2 Yazv/h+GiGt2+SRycZK36jgfj0mmS0ScCZskPwNRX/JvmzWym4b09UToOYzDE8dU mEGyu2++mN0qOuxg4r+O3fzdKYpNMJ5CGbryPQWys5vRQvWcWSjlxkjNZ4UlTcBR 6ZYoCN0KkRz24J4NIv4pVAGMvO/z4QAQA5wdgEZLe2keKnxhuPW5AsKHiEhBTkoN rgRiyoZ8lXgWhRZqOy2sqJSJR1t+lRv/B7gJiR+IoS3s/PJwB2V03PsgEC2PX4wc vxT2qy30mDcnHHbiLyVi6oWCjN2+Hn5NFG9EwXutzTx4ABn13JVegvl8Uq/uoUwQ JG7H9WJLRG+L0g== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppeduudekrddvuddtrddukedurdeh heenucevlhhushhtvghrufhiiigvpeegnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnh gurhgvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 2C5B0240054; Fri, 19 Mar 2021 02:28:48 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, chiawei_wang@aspeedtech.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 06/21] ipmi: kcs_bmc_aspeed: Use of match data to extract KCS properties Date: Fri, 19 Mar 2021 16:57:37 +1030 Message-Id: <20210319062752.145730-6-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Unpack and remove the aspeed_kcs_probe_of_v[12]() functions to aid rearranging how the private device-driver memory is allocated. Signed-off-by: Andrew Jeffery Tested-by: Chia-Wei Wang --- drivers/char/ipmi/kcs_bmc_aspeed.c | 146 ++++++++++++++--------------- 1 file changed, 68 insertions(+), 78 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index eefe362f65f0..061f53676206 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -63,6 +64,10 @@ struct aspeed_kcs_bmc { struct regmap *map; }; +struct aspeed_kcs_of_ops { + int (*get_channel)(struct platform_device *pdev); + int (*get_io_address)(struct platform_device *pdev); +}; static u8 aspeed_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) { @@ -231,13 +236,10 @@ static const struct kcs_ioreg ast_kcs_bmc_ioregs[KCS_CHANNEL_MAX] = { { .idr = LPC_IDR4, .odr = LPC_ODR4, .str = LPC_STR4 }, }; -static struct kcs_bmc *aspeed_kcs_probe_of_v1(struct platform_device *pdev) +static int aspeed_kcs_of_v1_get_channel(struct platform_device *pdev) { - struct aspeed_kcs_bmc *priv; struct device_node *np; - struct kcs_bmc *kcs; u32 channel; - u32 slave; int rc; np = pdev->dev.of_node; @@ -245,105 +247,78 @@ static struct kcs_bmc *aspeed_kcs_probe_of_v1(struct platform_device *pdev) rc = of_property_read_u32(np, "kcs_chan", &channel); if ((rc != 0) || (channel == 0 || channel > KCS_CHANNEL_MAX)) { dev_err(&pdev->dev, "no valid 'kcs_chan' configured\n"); - return ERR_PTR(-EINVAL); + return -EINVAL; } - kcs = kcs_bmc_alloc(&pdev->dev, sizeof(struct aspeed_kcs_bmc), channel); - if (!kcs) - return ERR_PTR(-ENOMEM); + return channel; +} - priv = kcs_bmc_priv(kcs); - priv->map = syscon_node_to_regmap(pdev->dev.parent->of_node); - if (IS_ERR(priv->map)) { - dev_err(&pdev->dev, "Couldn't get regmap\n"); - return ERR_PTR(-ENODEV); - } +static int aspeed_kcs_of_v1_get_io_address(struct platform_device *pdev) +{ + u32 slave; + int rc; - rc = of_property_read_u32(np, "kcs_addr", &slave); - if (rc) { + rc = of_property_read_u32(pdev->dev.of_node, "kcs_addr", &slave); + if (rc || slave > 0xffff) { dev_err(&pdev->dev, "no valid 'kcs_addr' configured\n"); - return ERR_PTR(-EINVAL); + return -EINVAL; } - kcs->ioreg = ast_kcs_bmc_ioregs[channel - 1]; - aspeed_kcs_set_address(kcs, slave); - - return kcs; -} - -static int aspeed_kcs_calculate_channel(const struct kcs_ioreg *regs) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ast_kcs_bmc_ioregs); i++) { - if (!memcmp(&ast_kcs_bmc_ioregs[i], regs, sizeof(*regs))) - return i + 1; - } - - return -EINVAL; + return slave; } -static struct kcs_bmc *aspeed_kcs_probe_of_v2(struct platform_device *pdev) +static int aspeed_kcs_of_v2_get_channel(struct platform_device *pdev) { - struct aspeed_kcs_bmc *priv; struct device_node *np; struct kcs_ioreg ioreg; - struct kcs_bmc *kcs; const __be32 *reg; - int channel; - u32 slave; - int rc; + int i; np = pdev->dev.of_node; /* Don't translate addresses, we want offsets for the regmaps */ reg = of_get_address(np, 0, NULL, NULL); if (!reg) - return ERR_PTR(-EINVAL); + return -EINVAL; ioreg.idr = be32_to_cpup(reg); reg = of_get_address(np, 1, NULL, NULL); if (!reg) - return ERR_PTR(-EINVAL); + return -EINVAL; ioreg.odr = be32_to_cpup(reg); reg = of_get_address(np, 2, NULL, NULL); if (!reg) - return ERR_PTR(-EINVAL); + return -EINVAL; ioreg.str = be32_to_cpup(reg); - channel = aspeed_kcs_calculate_channel(&ioreg); - if (channel < 0) - return ERR_PTR(channel); - - kcs = kcs_bmc_alloc(&pdev->dev, sizeof(struct aspeed_kcs_bmc), channel); - if (!kcs) - return ERR_PTR(-ENOMEM); - - kcs->ioreg = ioreg; - - priv = kcs_bmc_priv(kcs); - priv->map = syscon_node_to_regmap(pdev->dev.parent->of_node); - if (IS_ERR(priv->map)) { - dev_err(&pdev->dev, "Couldn't get regmap\n"); - return ERR_PTR(-ENODEV); + for (i = 0; i < ARRAY_SIZE(ast_kcs_bmc_ioregs); i++) { + if (!memcmp(&ast_kcs_bmc_ioregs[i], &ioreg, sizeof(ioreg))) + return i + 1; } - rc = of_property_read_u32(np, "aspeed,lpc-io-reg", &slave); - if (rc) - return ERR_PTR(rc); + return -EINVAL; +} - aspeed_kcs_set_address(kcs, slave); +static int aspeed_kcs_of_v2_get_io_address(struct platform_device *pdev) +{ + uint32_t slave; + int rc; - return kcs; + rc = of_property_read_u32(pdev->dev.of_node, "aspeed,lpc-io-reg", &slave); + if (rc || slave > 0xffff) + return -EINVAL; + + return slave; } static int aspeed_kcs_probe(struct platform_device *pdev) { + const struct aspeed_kcs_of_ops *ops; struct device *dev = &pdev->dev; struct kcs_bmc *kcs_bmc; struct device_node *np; - int rc; + int rc, channel, addr; np = dev->of_node->parent; if (!of_device_is_compatible(np, "aspeed,ast2400-lpc-v2") && @@ -352,23 +327,28 @@ static int aspeed_kcs_probe(struct platform_device *pdev) dev_err(dev, "unsupported LPC device binding\n"); return -ENODEV; } - - np = dev->of_node; - if (of_device_is_compatible(np, "aspeed,ast2400-kcs-bmc") || - of_device_is_compatible(np, "aspeed,ast2500-kcs-bmc")) - kcs_bmc = aspeed_kcs_probe_of_v1(pdev); - else if (of_device_is_compatible(np, "aspeed,ast2400-kcs-bmc-v2") || - of_device_is_compatible(np, "aspeed,ast2500-kcs-bmc-v2")) - kcs_bmc = aspeed_kcs_probe_of_v2(pdev); - else + ops = of_device_get_match_data(&pdev->dev); + if (!ops) return -EINVAL; - if (IS_ERR(kcs_bmc)) - return PTR_ERR(kcs_bmc); + channel = ops->get_channel(pdev); + if (channel < 0) + return channel; + kcs_bmc = kcs_bmc_alloc(&pdev->dev, sizeof(struct aspeed_kcs_bmc), channel); + if (!kcs_bmc) + return -ENOMEM; + + kcs_bmc->ioreg = ast_kcs_bmc_ioregs[channel - 1]; kcs_bmc->io_inputb = aspeed_kcs_inb; kcs_bmc->io_outputb = aspeed_kcs_outb; + addr = ops->get_io_address(pdev); + if (addr < 0) + return addr; + + aspeed_kcs_set_address(kcs_bmc, addr); + rc = aspeed_kcs_config_irq(kcs_bmc, pdev); if (rc) return rc; @@ -400,11 +380,21 @@ static int aspeed_kcs_remove(struct platform_device *pdev) return 0; } +static const struct aspeed_kcs_of_ops of_v1_ops = { + .get_channel = aspeed_kcs_of_v1_get_channel, + .get_io_address = aspeed_kcs_of_v1_get_io_address, +}; + +static const struct aspeed_kcs_of_ops of_v2_ops = { + .get_channel = aspeed_kcs_of_v2_get_channel, + .get_io_address = aspeed_kcs_of_v2_get_io_address, +}; + static const struct of_device_id ast_kcs_bmc_match[] = { - { .compatible = "aspeed,ast2400-kcs-bmc" }, - { .compatible = "aspeed,ast2500-kcs-bmc" }, - { .compatible = "aspeed,ast2400-kcs-bmc-v2" }, - { .compatible = "aspeed,ast2500-kcs-bmc-v2" }, + { .compatible = "aspeed,ast2400-kcs-bmc", .data = &of_v1_ops }, + { .compatible = "aspeed,ast2500-kcs-bmc", .data = &of_v1_ops }, + { .compatible = "aspeed,ast2400-kcs-bmc-v2", .data = &of_v2_ops }, + { .compatible = "aspeed,ast2500-kcs-bmc-v2", .data = &of_v2_ops }, { } }; MODULE_DEVICE_TABLE(of, ast_kcs_bmc_match); From patchwork Fri Mar 19 06:27:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455598 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=oERjuYIS; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=QX0i85yG; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vBf4zVZz9sWj for ; Fri, 19 Mar 2021 17:29:46 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234054AbhCSG3O (ORCPT ); Fri, 19 Mar 2021 02:29:14 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:37701 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233964AbhCSG3B (ORCPT ); Fri, 19 Mar 2021 02:29:01 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id B11C6580A7D; Fri, 19 Mar 2021 02:29:00 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:29:00 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=1OJCjYpu0WKYw rWXB0M7VMQlalIINkuei1N/8NZJJdU=; b=oERjuYISFCSJxKjbKgR/eZgJKmap/ 8pvwCrO8bb4Zqd87Iezz7KsA+JSkKC7CbA+8hDFvAG+Hrtw8TJD8e2jZe4S8j56/ Z5Lckdwh+c0vOtx3IJJt7pE0tijH8+48bRZqEppgWPugoEihX946vsRgZ9Ik28kc XOezLj8iQPXq4RySaxzb8Kp8WuGdqudGsmsNMuwLHoUNLx3oaVKf0YBmAJVSlKkU /RtrKihnIB49q4uoBx9HVehwRp3JlEvEJthORMq0tqTePm+iWKo74KenQgzS49Qm fzgACoKUNjyGuEYC3TdButZApFmOl30cH5nfeRoByBpVCm3tytZJt6WXQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=1OJCjYpu0WKYwrWXB0M7VMQlalIINkuei1N/8NZJJdU=; b=QX0i85yG HXJKjwxQ2dzXgPHKFWkkG8kpM9a1Why2lNBSGW81Wp6+x/t1vUVyj3Aeo/o16dyz 5Yvts0HlQY5y+dPQ0lBjhFzMXUu0RrCVodQV43fbd2ahZ9+2a9zVG6gy9lu93iiY wsVXfa677ivy0YrOZ1xuLWEYtCChnrwoQ4yWvkVvOpVojCfS+v2XomDcm4eZFiny WMAkbzWtBqbrF/Hbld7j/hKLZuL3vPsxJRnehVEVW4X2UahWZaGnm1xhYaXKJtU5 IPpkk728/WmdqsT0wTBhY9Izv3/DVq/KhqjINRIkoE0aB0u0Xlq1q7xGBgjmXBqO yphnPZ3VWouz3w== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppeduudekrddvuddtrddukedurdeh heenucevlhhushhtvghrufhiiigvpeehnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnh gurhgvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 27F11240054; Fri, 19 Mar 2021 02:28:54 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, chiawei_wang@aspeedtech.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 07/21] ipmi: kcs_bmc: Make status update atomic Date: Fri, 19 Mar 2021 16:57:38 +1030 Message-Id: <20210319062752.145730-7-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Enable more efficient implementation of read-modify-write sequences. Both device drivers for the KCS BMC stack use regmaps. The new callback allows us to exploit regmap_update_bits(). Signed-off-by: Andrew Jeffery Reviewed-by: Zev Weiss --- drivers/char/ipmi/kcs_bmc.c | 7 +------ drivers/char/ipmi/kcs_bmc.h | 1 + drivers/char/ipmi/kcs_bmc_aspeed.c | 9 +++++++++ drivers/char/ipmi/kcs_bmc_npcm7xx.c | 10 ++++++++++ 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index f292e74bd4a5..58fb1a7bd50d 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -67,12 +67,7 @@ static inline void write_status(struct kcs_bmc *kcs_bmc, u8 data) static void update_status_bits(struct kcs_bmc *kcs_bmc, u8 mask, u8 val) { - u8 tmp = read_status(kcs_bmc); - - tmp &= ~mask; - tmp |= val & mask; - - write_status(kcs_bmc, tmp); + kcs_bmc->io_updateb(kcs_bmc, kcs_bmc->ioreg.str, mask, val); } static inline void set_state(struct kcs_bmc *kcs_bmc, u8 state) diff --git a/drivers/char/ipmi/kcs_bmc.h b/drivers/char/ipmi/kcs_bmc.h index eb9ea4ce78b8..970f53892f2d 100644 --- a/drivers/char/ipmi/kcs_bmc.h +++ b/drivers/char/ipmi/kcs_bmc.h @@ -76,6 +76,7 @@ struct kcs_bmc { struct kcs_ioreg ioreg; u8 (*io_inputb)(struct kcs_bmc *kcs_bmc, u32 reg); void (*io_outputb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 b); + void (*io_updateb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val); enum kcs_phases phase; enum kcs_errors error; diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 061f53676206..630cf095560e 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -90,6 +90,14 @@ static void aspeed_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) WARN(rc != 0, "regmap_write() failed: %d\n", rc); } +static void aspeed_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val) +{ + struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + int rc; + + rc = regmap_update_bits(priv->map, reg, mask, val); + WARN(rc != 0, "regmap_update_bits() failed: %d\n", rc); +} /* * AST_usrGuide_KCS.pdf @@ -342,6 +350,7 @@ static int aspeed_kcs_probe(struct platform_device *pdev) kcs_bmc->ioreg = ast_kcs_bmc_ioregs[channel - 1]; kcs_bmc->io_inputb = aspeed_kcs_inb; kcs_bmc->io_outputb = aspeed_kcs_outb; + kcs_bmc->io_updateb = aspeed_kcs_updateb; addr = ops->get_io_address(pdev); if (addr < 0) diff --git a/drivers/char/ipmi/kcs_bmc_npcm7xx.c b/drivers/char/ipmi/kcs_bmc_npcm7xx.c index 722f7391fe1f..1f44aadec9e8 100644 --- a/drivers/char/ipmi/kcs_bmc_npcm7xx.c +++ b/drivers/char/ipmi/kcs_bmc_npcm7xx.c @@ -97,6 +97,15 @@ static void npcm7xx_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) WARN(rc != 0, "regmap_write() failed: %d\n", rc); } +static void npcm7xx_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 data) +{ + struct npcm7xx_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + int rc; + + rc = regmap_update_bits(priv->map, reg, mask, data); + WARN(rc != 0, "regmap_update_bits() failed: %d\n", rc); +} + static void npcm7xx_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable) { struct npcm7xx_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); @@ -163,6 +172,7 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) kcs_bmc->ioreg.str = priv->reg->sts; kcs_bmc->io_inputb = npcm7xx_kcs_inb; kcs_bmc->io_outputb = npcm7xx_kcs_outb; + kcs_bmc->io_updateb = npcm7xx_kcs_updateb; dev_set_drvdata(dev, kcs_bmc); From patchwork Fri Mar 19 06:27:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455597 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=dJHIGZon; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=ui8I7kmD; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vBf2dPGz9sVS for ; Fri, 19 Mar 2021 17:29:46 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234060AbhCSG3Q (ORCPT ); Fri, 19 Mar 2021 02:29:16 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:59067 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234034AbhCSG3H (ORCPT ); Fri, 19 Mar 2021 02:29:07 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id AD96A580A81; Fri, 19 Mar 2021 02:29:06 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:29:06 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=Ko3OKT6VnAb6a e+1fgFzozhFm1BKXxGAhRiRJMA4uKI=; b=dJHIGZonpQ9HTdVw6aF1QAjUoxsM7 QmmVt+2eKii03UKH0XsdUlvRObCRodWTTQI6TJtbiikzxo/9t0SQFWGfvuGFNxhV fPt4aR2g3yFr4WC15pXcsoczB5XXjniRC+RbRPYkJFazUWX+rlxJ1HLq23j9cAoB Hmekauk0yLdkN5YT2Wbx16igH1+5vFcOvZ27EPM4EELyC9assOLm9xMJSLG344cn 4EXoG7tDDzQOMVzUIwryvSkFHszhMePxZjUM5CbPWfVL3Xu3T3OfwNv3NYC8kP4H FnMxxpztcvP3ieP7QJ3kW46pc00f+zbof8Y4dKOgw6l1F923SIIWsiwCw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=Ko3OKT6VnAb6ae+1fgFzozhFm1BKXxGAhRiRJMA4uKI=; b=ui8I7kmD 5yewb3FXgYVAoBena9UGppFRLeStah0n/1XXYxR122UdwtfjG9BiuZXMjYUmxnym +Lm27cPyg0EAb3/eehEO7+RiejNZNBWH8pYIiOztAlnemWuXw+asV6i+2qTLJNvq hU0WD4HbYo6u1U0fkNWujXKukww6CFKrh2iWHFJii4HMZiYqYssZQyFwhmY0FKrH plI4CXXoAQbXsO35xJ3SdighbnLRCRqcnZaKf5baGKJr0mZRlxdUwNPhbusfwYsx 5/9rPOXSZQbPb5cC3nc8SqoQZbDuQNEcvQ6MYbGAdqKkUG3fzZFW8xFsLHGlfAmz Jr6WeC24MmeFNA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppeduudekrddvuddtrddukedurdeh heenucevlhhushhtvghrufhiiigvpeeinecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnh gurhgvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 1F558240054; Fri, 19 Mar 2021 02:29:00 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, chiawei_wang@aspeedtech.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 08/21] ipmi: kcs_bmc: Rename {read,write}_{status,data}() functions Date: Fri, 19 Mar 2021 16:57:39 +1030 Message-Id: <20210319062752.145730-8-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Rename the functions in preparation for separating the IPMI chardev out from the KCS BMC core. Signed-off-by: Andrew Jeffery Reviewed-by: Zev Weiss --- drivers/char/ipmi/kcs_bmc.c | 52 ++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index 58fb1a7bd50d..c4336c1f2d6d 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -45,42 +45,42 @@ enum kcs_states { #define KCS_CMD_WRITE_END 0x62 #define KCS_CMD_READ_BYTE 0x68 -static inline u8 read_data(struct kcs_bmc *kcs_bmc) +static inline u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc) { return kcs_bmc->io_inputb(kcs_bmc, kcs_bmc->ioreg.idr); } -static inline void write_data(struct kcs_bmc *kcs_bmc, u8 data) +static inline void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data) { kcs_bmc->io_outputb(kcs_bmc, kcs_bmc->ioreg.odr, data); } -static inline u8 read_status(struct kcs_bmc *kcs_bmc) +static inline u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc) { return kcs_bmc->io_inputb(kcs_bmc, kcs_bmc->ioreg.str); } -static inline void write_status(struct kcs_bmc *kcs_bmc, u8 data) +static inline void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data) { kcs_bmc->io_outputb(kcs_bmc, kcs_bmc->ioreg.str, data); } -static void update_status_bits(struct kcs_bmc *kcs_bmc, u8 mask, u8 val) +static void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val) { kcs_bmc->io_updateb(kcs_bmc, kcs_bmc->ioreg.str, mask, val); } static inline void set_state(struct kcs_bmc *kcs_bmc, u8 state) { - update_status_bits(kcs_bmc, KCS_STATUS_STATE_MASK, + kcs_bmc_update_status(kcs_bmc, KCS_STATUS_STATE_MASK, KCS_STATUS_STATE(state)); } static void kcs_force_abort(struct kcs_bmc *kcs_bmc) { set_state(kcs_bmc, ERROR_STATE); - read_data(kcs_bmc); - write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc_read_data(kcs_bmc); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); kcs_bmc->phase = KCS_PHASE_ERROR; kcs_bmc->data_in_avail = false; @@ -99,9 +99,9 @@ static void kcs_bmc_handle_data(struct kcs_bmc *kcs_bmc) case KCS_PHASE_WRITE_DATA: if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { set_state(kcs_bmc, WRITE_STATE); - write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); kcs_bmc->data_in[kcs_bmc->data_in_idx++] = - read_data(kcs_bmc); + kcs_bmc_read_data(kcs_bmc); } else { kcs_force_abort(kcs_bmc); kcs_bmc->error = KCS_LENGTH_ERROR; @@ -112,7 +112,7 @@ static void kcs_bmc_handle_data(struct kcs_bmc *kcs_bmc) if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { set_state(kcs_bmc, READ_STATE); kcs_bmc->data_in[kcs_bmc->data_in_idx++] = - read_data(kcs_bmc); + kcs_bmc_read_data(kcs_bmc); kcs_bmc->phase = KCS_PHASE_WRITE_DONE; kcs_bmc->data_in_avail = true; wake_up_interruptible(&kcs_bmc->queue); @@ -126,34 +126,34 @@ static void kcs_bmc_handle_data(struct kcs_bmc *kcs_bmc) if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) set_state(kcs_bmc, IDLE_STATE); - data = read_data(kcs_bmc); + data = kcs_bmc_read_data(kcs_bmc); if (data != KCS_CMD_READ_BYTE) { set_state(kcs_bmc, ERROR_STATE); - write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); break; } if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) { - write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); kcs_bmc->phase = KCS_PHASE_IDLE; break; } - write_data(kcs_bmc, + kcs_bmc_write_data(kcs_bmc, kcs_bmc->data_out[kcs_bmc->data_out_idx++]); break; case KCS_PHASE_ABORT_ERROR1: set_state(kcs_bmc, READ_STATE); - read_data(kcs_bmc); - write_data(kcs_bmc, kcs_bmc->error); + kcs_bmc_read_data(kcs_bmc); + kcs_bmc_write_data(kcs_bmc, kcs_bmc->error); kcs_bmc->phase = KCS_PHASE_ABORT_ERROR2; break; case KCS_PHASE_ABORT_ERROR2: set_state(kcs_bmc, IDLE_STATE); - read_data(kcs_bmc); - write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc_read_data(kcs_bmc); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); kcs_bmc->phase = KCS_PHASE_IDLE; break; @@ -168,9 +168,9 @@ static void kcs_bmc_handle_cmd(struct kcs_bmc *kcs_bmc) u8 cmd; set_state(kcs_bmc, WRITE_STATE); - write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - cmd = read_data(kcs_bmc); + cmd = kcs_bmc_read_data(kcs_bmc); switch (cmd) { case KCS_CMD_WRITE_START: kcs_bmc->phase = KCS_PHASE_WRITE_START; @@ -212,7 +212,7 @@ int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc) spin_lock_irqsave(&kcs_bmc->lock, flags); - status = read_status(kcs_bmc); + status = kcs_bmc_read_status(kcs_bmc); if (status & KCS_STATUS_IBF) { if (!kcs_bmc->running) kcs_force_abort(kcs_bmc); @@ -350,7 +350,7 @@ static ssize_t kcs_bmc_write(struct file *filp, const char __user *buf, kcs_bmc->data_out_idx = 1; kcs_bmc->data_out_len = count; memcpy(kcs_bmc->data_out, kcs_bmc->kbuffer, count); - write_data(kcs_bmc, kcs_bmc->data_out[0]); + kcs_bmc_write_data(kcs_bmc, kcs_bmc->data_out[0]); ret = count; } else { ret = -EINVAL; @@ -373,13 +373,11 @@ static long kcs_bmc_ioctl(struct file *filp, unsigned int cmd, switch (cmd) { case IPMI_BMC_IOCTL_SET_SMS_ATN: - update_status_bits(kcs_bmc, KCS_STATUS_SMS_ATN, - KCS_STATUS_SMS_ATN); + kcs_bmc_update_status(kcs_bmc, KCS_STATUS_SMS_ATN, KCS_STATUS_SMS_ATN); break; case IPMI_BMC_IOCTL_CLEAR_SMS_ATN: - update_status_bits(kcs_bmc, KCS_STATUS_SMS_ATN, - 0); + kcs_bmc_update_status(kcs_bmc, KCS_STATUS_SMS_ATN, 0); break; case IPMI_BMC_IOCTL_FORCE_ABORT: From patchwork Fri Mar 19 06:27:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455604 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=Rjt3gv0q; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=c8sb95pu; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vCJ4zNnz9sVS for ; Fri, 19 Mar 2021 17:30:16 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234044AbhCSG3m (ORCPT ); Fri, 19 Mar 2021 02:29:42 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:58153 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234047AbhCSG3N (ORCPT ); Fri, 19 Mar 2021 02:29:13 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id F03F6580A7C; Fri, 19 Mar 2021 02:29:12 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:29:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=yXRvjFnul01I5 WTdhI9xDz5pCw3tfQoAQK0ZMPAotmE=; b=Rjt3gv0qQhnYWDdr2GxOXCaTIEycA r03qtgmQSnIP8DsQKnKbYXlguNeJR7+xdgOZRJhkh0Zd/tiOhn4f/oJKMeHQDJl0 PpXzeYgUE4SLZwnlJYJtbQKoMxXph3KRXn+BeJnQdgfFY6UAOvYaGKORgkb2zMIJ BNwHv1BSwD4i+yqGXim41t4aWhPCreJ4V0iKULF5eA49olRqxZqboGbmXPAEb3UW dnsmaLrTFFnp9OQ7ywTBC2ysAmnKDMJeVDPgxVA1Zo+Ji5psXj5uofpsZQyBQNV5 Z4OBv+M1rEVnTlk1fxNhbFb3RylOhvEeR3Zt7PiygNhJPQMcOwMun6ujQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=yXRvjFnul01I5WTdhI9xDz5pCw3tfQoAQK0ZMPAotmE=; b=c8sb95pu 6RFpveWEc2lGehpy/kYPXXbnsl4H1E5zOGkJkMvWhcD/d3sHT3PpQkbKvUTllFph nOHyaIkR3bbj5N73JVKIhJg4RNHZdNCJU2I4/UXi/SKYtFNWbOFTLcu1yzS9NcbO E+IZYHsAKd/R3/GN0akmIV6lftoyiY7sXKG5Kq50LEKnVE4czMKH0rmbpR7IJU9Z dOUri2GmDlEa0u/Gm0Y1c8AdobA/UOZLqNAdDJv+pSy2u0P8I6k+EX/4y4iVeMYs JIJyZxcOyp7SQdwwfDvop1wcXW9YU460G1OomT49t7kH+4uRjTeXl6qYt+59EboQ iSmCzVPL7s+/vg== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppeduudekrddvuddtrddukedurdeh heenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnh gurhgvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 1E890240057; Fri, 19 Mar 2021 02:29:06 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, chiawei_wang@aspeedtech.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 09/21] ipmi: kcs_bmc: Split out kcs_bmc_cdev_ipmi Date: Fri, 19 Mar 2021 16:57:40 +1030 Message-Id: <20210319062752.145730-9-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Take steps towards defining a coherent API to separate the KCS device drivers from the userspace interface. Decreasing the coupling will improve the separation of concerns and enable the introduction of alternative userspace interfaces. For now, simply split the chardev logic out to a separate file. The code continues to build into the same module. Signed-off-by: Andrew Jeffery Reviewed-by: Zev Weiss --- drivers/char/ipmi/Makefile | 2 +- drivers/char/ipmi/kcs_bmc.c | 423 +------------------------ drivers/char/ipmi/kcs_bmc.h | 10 +- drivers/char/ipmi/kcs_bmc_cdev_ipmi.c | 428 ++++++++++++++++++++++++++ 4 files changed, 451 insertions(+), 412 deletions(-) create mode 100644 drivers/char/ipmi/kcs_bmc_cdev_ipmi.c diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile index 0822adc2ec41..a302bc865370 100644 --- a/drivers/char/ipmi/Makefile +++ b/drivers/char/ipmi/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_IPMI_SSIF) += ipmi_ssif.o obj-$(CONFIG_IPMI_POWERNV) += ipmi_powernv.o obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o -obj-$(CONFIG_IPMI_KCS_BMC) += kcs_bmc.o +obj-$(CONFIG_IPMI_KCS_BMC) += kcs_bmc.o kcs_bmc_cdev_ipmi.o obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o obj-$(CONFIG_ASPEED_KCS_IPMI_BMC) += kcs_bmc_aspeed.o obj-$(CONFIG_NPCM7XX_KCS_IPMI_BMC) += kcs_bmc_npcm7xx.o diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index c4336c1f2d6d..ef5c48ffe74a 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -3,446 +3,51 @@ * Copyright (c) 2015-2018, Intel Corporation. */ -#define pr_fmt(fmt) "kcs-bmc: " fmt - -#include -#include -#include #include -#include -#include -#include -#include #include "kcs_bmc.h" -#define DEVICE_NAME "ipmi-kcs" - -#define KCS_MSG_BUFSIZ 1000 - -#define KCS_ZERO_DATA 0 - - -/* IPMI 2.0 - Table 9-1, KCS Interface Status Register Bits */ -#define KCS_STATUS_STATE(state) (state << 6) -#define KCS_STATUS_STATE_MASK GENMASK(7, 6) -#define KCS_STATUS_CMD_DAT BIT(3) -#define KCS_STATUS_SMS_ATN BIT(2) -#define KCS_STATUS_IBF BIT(1) -#define KCS_STATUS_OBF BIT(0) - -/* IPMI 2.0 - Table 9-2, KCS Interface State Bits */ -enum kcs_states { - IDLE_STATE = 0, - READ_STATE = 1, - WRITE_STATE = 2, - ERROR_STATE = 3, -}; - -/* IPMI 2.0 - Table 9-3, KCS Interface Control Codes */ -#define KCS_CMD_GET_STATUS_ABORT 0x60 -#define KCS_CMD_WRITE_START 0x61 -#define KCS_CMD_WRITE_END 0x62 -#define KCS_CMD_READ_BYTE 0x68 - -static inline u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc) +u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc) { return kcs_bmc->io_inputb(kcs_bmc, kcs_bmc->ioreg.idr); } +EXPORT_SYMBOL(kcs_bmc_read_data); -static inline void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data) +void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data) { kcs_bmc->io_outputb(kcs_bmc, kcs_bmc->ioreg.odr, data); } +EXPORT_SYMBOL(kcs_bmc_write_data); -static inline u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc) +u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc) { return kcs_bmc->io_inputb(kcs_bmc, kcs_bmc->ioreg.str); } +EXPORT_SYMBOL(kcs_bmc_read_status); -static inline void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data) +void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data) { kcs_bmc->io_outputb(kcs_bmc, kcs_bmc->ioreg.str, data); } +EXPORT_SYMBOL(kcs_bmc_write_status); -static void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val) +void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val) { kcs_bmc->io_updateb(kcs_bmc, kcs_bmc->ioreg.str, mask, val); } +EXPORT_SYMBOL(kcs_bmc_update_status); -static inline void set_state(struct kcs_bmc *kcs_bmc, u8 state) -{ - kcs_bmc_update_status(kcs_bmc, KCS_STATUS_STATE_MASK, - KCS_STATUS_STATE(state)); -} - -static void kcs_force_abort(struct kcs_bmc *kcs_bmc) -{ - set_state(kcs_bmc, ERROR_STATE); - kcs_bmc_read_data(kcs_bmc); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - - kcs_bmc->phase = KCS_PHASE_ERROR; - kcs_bmc->data_in_avail = false; - kcs_bmc->data_in_idx = 0; -} - -static void kcs_bmc_handle_data(struct kcs_bmc *kcs_bmc) -{ - u8 data; - - switch (kcs_bmc->phase) { - case KCS_PHASE_WRITE_START: - kcs_bmc->phase = KCS_PHASE_WRITE_DATA; - fallthrough; - - case KCS_PHASE_WRITE_DATA: - if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { - set_state(kcs_bmc, WRITE_STATE); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - kcs_bmc->data_in[kcs_bmc->data_in_idx++] = - kcs_bmc_read_data(kcs_bmc); - } else { - kcs_force_abort(kcs_bmc); - kcs_bmc->error = KCS_LENGTH_ERROR; - } - break; - - case KCS_PHASE_WRITE_END_CMD: - if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { - set_state(kcs_bmc, READ_STATE); - kcs_bmc->data_in[kcs_bmc->data_in_idx++] = - kcs_bmc_read_data(kcs_bmc); - kcs_bmc->phase = KCS_PHASE_WRITE_DONE; - kcs_bmc->data_in_avail = true; - wake_up_interruptible(&kcs_bmc->queue); - } else { - kcs_force_abort(kcs_bmc); - kcs_bmc->error = KCS_LENGTH_ERROR; - } - break; - - case KCS_PHASE_READ: - if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) - set_state(kcs_bmc, IDLE_STATE); - - data = kcs_bmc_read_data(kcs_bmc); - if (data != KCS_CMD_READ_BYTE) { - set_state(kcs_bmc, ERROR_STATE); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - break; - } - - if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) { - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - kcs_bmc->phase = KCS_PHASE_IDLE; - break; - } - - kcs_bmc_write_data(kcs_bmc, - kcs_bmc->data_out[kcs_bmc->data_out_idx++]); - break; - - case KCS_PHASE_ABORT_ERROR1: - set_state(kcs_bmc, READ_STATE); - kcs_bmc_read_data(kcs_bmc); - kcs_bmc_write_data(kcs_bmc, kcs_bmc->error); - kcs_bmc->phase = KCS_PHASE_ABORT_ERROR2; - break; - - case KCS_PHASE_ABORT_ERROR2: - set_state(kcs_bmc, IDLE_STATE); - kcs_bmc_read_data(kcs_bmc); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - kcs_bmc->phase = KCS_PHASE_IDLE; - break; - - default: - kcs_force_abort(kcs_bmc); - break; - } -} - -static void kcs_bmc_handle_cmd(struct kcs_bmc *kcs_bmc) -{ - u8 cmd; - - set_state(kcs_bmc, WRITE_STATE); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - - cmd = kcs_bmc_read_data(kcs_bmc); - switch (cmd) { - case KCS_CMD_WRITE_START: - kcs_bmc->phase = KCS_PHASE_WRITE_START; - kcs_bmc->error = KCS_NO_ERROR; - kcs_bmc->data_in_avail = false; - kcs_bmc->data_in_idx = 0; - break; - - case KCS_CMD_WRITE_END: - if (kcs_bmc->phase != KCS_PHASE_WRITE_DATA) { - kcs_force_abort(kcs_bmc); - break; - } - - kcs_bmc->phase = KCS_PHASE_WRITE_END_CMD; - break; - - case KCS_CMD_GET_STATUS_ABORT: - if (kcs_bmc->error == KCS_NO_ERROR) - kcs_bmc->error = KCS_ABORTED_BY_COMMAND; - - kcs_bmc->phase = KCS_PHASE_ABORT_ERROR1; - kcs_bmc->data_in_avail = false; - kcs_bmc->data_in_idx = 0; - break; - - default: - kcs_force_abort(kcs_bmc); - kcs_bmc->error = KCS_ILLEGAL_CONTROL_CODE; - break; - } -} - +int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc); int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc) { - unsigned long flags; - int ret = -ENODATA; - u8 status; - - spin_lock_irqsave(&kcs_bmc->lock, flags); - - status = kcs_bmc_read_status(kcs_bmc); - if (status & KCS_STATUS_IBF) { - if (!kcs_bmc->running) - kcs_force_abort(kcs_bmc); - else if (status & KCS_STATUS_CMD_DAT) - kcs_bmc_handle_cmd(kcs_bmc); - else - kcs_bmc_handle_data(kcs_bmc); - - ret = 0; - } - - spin_unlock_irqrestore(&kcs_bmc->lock, flags); - - return ret; + return kcs_bmc_ipmi_event(kcs_bmc); } EXPORT_SYMBOL(kcs_bmc_handle_event); -static inline struct kcs_bmc *to_kcs_bmc(struct file *filp) -{ - return container_of(filp->private_data, struct kcs_bmc, miscdev); -} - -static int kcs_bmc_open(struct inode *inode, struct file *filp) -{ - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); - int ret = 0; - - spin_lock_irq(&kcs_bmc->lock); - if (!kcs_bmc->running) - kcs_bmc->running = 1; - else - ret = -EBUSY; - spin_unlock_irq(&kcs_bmc->lock); - - return ret; -} - -static __poll_t kcs_bmc_poll(struct file *filp, poll_table *wait) -{ - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); - __poll_t mask = 0; - - poll_wait(filp, &kcs_bmc->queue, wait); - - spin_lock_irq(&kcs_bmc->lock); - if (kcs_bmc->data_in_avail) - mask |= EPOLLIN; - spin_unlock_irq(&kcs_bmc->lock); - - return mask; -} - -static ssize_t kcs_bmc_read(struct file *filp, char __user *buf, - size_t count, loff_t *ppos) -{ - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); - bool data_avail; - size_t data_len; - ssize_t ret; - - if (!(filp->f_flags & O_NONBLOCK)) - wait_event_interruptible(kcs_bmc->queue, - kcs_bmc->data_in_avail); - - mutex_lock(&kcs_bmc->mutex); - - spin_lock_irq(&kcs_bmc->lock); - data_avail = kcs_bmc->data_in_avail; - if (data_avail) { - data_len = kcs_bmc->data_in_idx; - memcpy(kcs_bmc->kbuffer, kcs_bmc->data_in, data_len); - } - spin_unlock_irq(&kcs_bmc->lock); - - if (!data_avail) { - ret = -EAGAIN; - goto out_unlock; - } - - if (count < data_len) { - pr_err("channel=%u with too large data : %zu\n", - kcs_bmc->channel, data_len); - - spin_lock_irq(&kcs_bmc->lock); - kcs_force_abort(kcs_bmc); - spin_unlock_irq(&kcs_bmc->lock); - - ret = -EOVERFLOW; - goto out_unlock; - } - - if (copy_to_user(buf, kcs_bmc->kbuffer, data_len)) { - ret = -EFAULT; - goto out_unlock; - } - - ret = data_len; - - spin_lock_irq(&kcs_bmc->lock); - if (kcs_bmc->phase == KCS_PHASE_WRITE_DONE) { - kcs_bmc->phase = KCS_PHASE_WAIT_READ; - kcs_bmc->data_in_avail = false; - kcs_bmc->data_in_idx = 0; - } else { - ret = -EAGAIN; - } - spin_unlock_irq(&kcs_bmc->lock); - -out_unlock: - mutex_unlock(&kcs_bmc->mutex); - - return ret; -} - -static ssize_t kcs_bmc_write(struct file *filp, const char __user *buf, - size_t count, loff_t *ppos) -{ - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); - ssize_t ret; - - /* a minimum response size '3' : netfn + cmd + ccode */ - if (count < 3 || count > KCS_MSG_BUFSIZ) - return -EINVAL; - - mutex_lock(&kcs_bmc->mutex); - - if (copy_from_user(kcs_bmc->kbuffer, buf, count)) { - ret = -EFAULT; - goto out_unlock; - } - - spin_lock_irq(&kcs_bmc->lock); - if (kcs_bmc->phase == KCS_PHASE_WAIT_READ) { - kcs_bmc->phase = KCS_PHASE_READ; - kcs_bmc->data_out_idx = 1; - kcs_bmc->data_out_len = count; - memcpy(kcs_bmc->data_out, kcs_bmc->kbuffer, count); - kcs_bmc_write_data(kcs_bmc, kcs_bmc->data_out[0]); - ret = count; - } else { - ret = -EINVAL; - } - spin_unlock_irq(&kcs_bmc->lock); - -out_unlock: - mutex_unlock(&kcs_bmc->mutex); - - return ret; -} - -static long kcs_bmc_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); - long ret = 0; - - spin_lock_irq(&kcs_bmc->lock); - - switch (cmd) { - case IPMI_BMC_IOCTL_SET_SMS_ATN: - kcs_bmc_update_status(kcs_bmc, KCS_STATUS_SMS_ATN, KCS_STATUS_SMS_ATN); - break; - - case IPMI_BMC_IOCTL_CLEAR_SMS_ATN: - kcs_bmc_update_status(kcs_bmc, KCS_STATUS_SMS_ATN, 0); - break; - - case IPMI_BMC_IOCTL_FORCE_ABORT: - kcs_force_abort(kcs_bmc); - break; - - default: - ret = -EINVAL; - break; - } - - spin_unlock_irq(&kcs_bmc->lock); - - return ret; -} - -static int kcs_bmc_release(struct inode *inode, struct file *filp) -{ - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); - - spin_lock_irq(&kcs_bmc->lock); - kcs_bmc->running = 0; - kcs_force_abort(kcs_bmc); - spin_unlock_irq(&kcs_bmc->lock); - - return 0; -} - -static const struct file_operations kcs_bmc_fops = { - .owner = THIS_MODULE, - .open = kcs_bmc_open, - .read = kcs_bmc_read, - .write = kcs_bmc_write, - .release = kcs_bmc_release, - .poll = kcs_bmc_poll, - .unlocked_ioctl = kcs_bmc_ioctl, -}; - +struct kcs_bmc *kcs_bmc_ipmi_alloc(struct device *dev, int sizeof_priv, u32 channel); struct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv, u32 channel) { - struct kcs_bmc *kcs_bmc; - - kcs_bmc = devm_kzalloc(dev, sizeof(*kcs_bmc) + sizeof_priv, GFP_KERNEL); - if (!kcs_bmc) - return NULL; - - spin_lock_init(&kcs_bmc->lock); - kcs_bmc->channel = channel; - - mutex_init(&kcs_bmc->mutex); - init_waitqueue_head(&kcs_bmc->queue); - - kcs_bmc->data_in = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); - kcs_bmc->data_out = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); - kcs_bmc->kbuffer = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); - - kcs_bmc->miscdev.minor = MISC_DYNAMIC_MINOR; - kcs_bmc->miscdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s%u", - DEVICE_NAME, channel); - if (!kcs_bmc->data_in || !kcs_bmc->data_out || !kcs_bmc->kbuffer || - !kcs_bmc->miscdev.name) - return NULL; - kcs_bmc->miscdev.fops = &kcs_bmc_fops; - - return kcs_bmc; + return kcs_bmc_ipmi_alloc(dev, sizeof_priv, channel); } EXPORT_SYMBOL(kcs_bmc_alloc); diff --git a/drivers/char/ipmi/kcs_bmc.h b/drivers/char/ipmi/kcs_bmc.h index 970f53892f2d..febea0c8deb4 100644 --- a/drivers/char/ipmi/kcs_bmc.h +++ b/drivers/char/ipmi/kcs_bmc.h @@ -104,6 +104,12 @@ static inline void *kcs_bmc_priv(struct kcs_bmc *kcs_bmc) } int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc); -struct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv, - u32 channel); +struct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv, u32 channel); + +u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc); +void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data); +u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc); +void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data); +void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val); + #endif /* __KCS_BMC_H__ */ diff --git a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c new file mode 100644 index 000000000000..82c77994e481 --- /dev/null +++ b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c @@ -0,0 +1,428 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2015-2018, Intel Corporation. + */ + +#define pr_fmt(fmt) "kcs-bmc: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kcs_bmc.h" + +#define DEVICE_NAME "ipmi-kcs" + +#define KCS_MSG_BUFSIZ 1000 + +#define KCS_ZERO_DATA 0 + + +/* IPMI 2.0 - Table 9-1, KCS Interface Status Register Bits */ +#define KCS_STATUS_STATE(state) (state << 6) +#define KCS_STATUS_STATE_MASK GENMASK(7, 6) +#define KCS_STATUS_CMD_DAT BIT(3) +#define KCS_STATUS_SMS_ATN BIT(2) +#define KCS_STATUS_IBF BIT(1) +#define KCS_STATUS_OBF BIT(0) + +/* IPMI 2.0 - Table 9-2, KCS Interface State Bits */ +enum kcs_states { + IDLE_STATE = 0, + READ_STATE = 1, + WRITE_STATE = 2, + ERROR_STATE = 3, +}; + +/* IPMI 2.0 - Table 9-3, KCS Interface Control Codes */ +#define KCS_CMD_GET_STATUS_ABORT 0x60 +#define KCS_CMD_WRITE_START 0x61 +#define KCS_CMD_WRITE_END 0x62 +#define KCS_CMD_READ_BYTE 0x68 + +static inline void set_state(struct kcs_bmc *kcs_bmc, u8 state) +{ + kcs_bmc_update_status(kcs_bmc, KCS_STATUS_STATE_MASK, + KCS_STATUS_STATE(state)); +} + +static void kcs_bmc_ipmi_force_abort(struct kcs_bmc *kcs_bmc) +{ + set_state(kcs_bmc, ERROR_STATE); + kcs_bmc_read_data(kcs_bmc); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + + kcs_bmc->phase = KCS_PHASE_ERROR; + kcs_bmc->data_in_avail = false; + kcs_bmc->data_in_idx = 0; +} + +static void kcs_bmc_ipmi_handle_data(struct kcs_bmc *kcs_bmc) +{ + u8 data; + + switch (kcs_bmc->phase) { + case KCS_PHASE_WRITE_START: + kcs_bmc->phase = KCS_PHASE_WRITE_DATA; + fallthrough; + + case KCS_PHASE_WRITE_DATA: + if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { + set_state(kcs_bmc, WRITE_STATE); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc->data_in[kcs_bmc->data_in_idx++] = + kcs_bmc_read_data(kcs_bmc); + } else { + kcs_bmc_ipmi_force_abort(kcs_bmc); + kcs_bmc->error = KCS_LENGTH_ERROR; + } + break; + + case KCS_PHASE_WRITE_END_CMD: + if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { + set_state(kcs_bmc, READ_STATE); + kcs_bmc->data_in[kcs_bmc->data_in_idx++] = + kcs_bmc_read_data(kcs_bmc); + kcs_bmc->phase = KCS_PHASE_WRITE_DONE; + kcs_bmc->data_in_avail = true; + wake_up_interruptible(&kcs_bmc->queue); + } else { + kcs_bmc_ipmi_force_abort(kcs_bmc); + kcs_bmc->error = KCS_LENGTH_ERROR; + } + break; + + case KCS_PHASE_READ: + if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) + set_state(kcs_bmc, IDLE_STATE); + + data = kcs_bmc_read_data(kcs_bmc); + if (data != KCS_CMD_READ_BYTE) { + set_state(kcs_bmc, ERROR_STATE); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + break; + } + + if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) { + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc->phase = KCS_PHASE_IDLE; + break; + } + + kcs_bmc_write_data(kcs_bmc, + kcs_bmc->data_out[kcs_bmc->data_out_idx++]); + break; + + case KCS_PHASE_ABORT_ERROR1: + set_state(kcs_bmc, READ_STATE); + kcs_bmc_read_data(kcs_bmc); + kcs_bmc_write_data(kcs_bmc, kcs_bmc->error); + kcs_bmc->phase = KCS_PHASE_ABORT_ERROR2; + break; + + case KCS_PHASE_ABORT_ERROR2: + set_state(kcs_bmc, IDLE_STATE); + kcs_bmc_read_data(kcs_bmc); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + kcs_bmc->phase = KCS_PHASE_IDLE; + break; + + default: + kcs_bmc_ipmi_force_abort(kcs_bmc); + break; + } +} + +static void kcs_bmc_ipmi_handle_cmd(struct kcs_bmc *kcs_bmc) +{ + u8 cmd; + + set_state(kcs_bmc, WRITE_STATE); + kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + + cmd = kcs_bmc_read_data(kcs_bmc); + switch (cmd) { + case KCS_CMD_WRITE_START: + kcs_bmc->phase = KCS_PHASE_WRITE_START; + kcs_bmc->error = KCS_NO_ERROR; + kcs_bmc->data_in_avail = false; + kcs_bmc->data_in_idx = 0; + break; + + case KCS_CMD_WRITE_END: + if (kcs_bmc->phase != KCS_PHASE_WRITE_DATA) { + kcs_bmc_ipmi_force_abort(kcs_bmc); + break; + } + + kcs_bmc->phase = KCS_PHASE_WRITE_END_CMD; + break; + + case KCS_CMD_GET_STATUS_ABORT: + if (kcs_bmc->error == KCS_NO_ERROR) + kcs_bmc->error = KCS_ABORTED_BY_COMMAND; + + kcs_bmc->phase = KCS_PHASE_ABORT_ERROR1; + kcs_bmc->data_in_avail = false; + kcs_bmc->data_in_idx = 0; + break; + + default: + kcs_bmc_ipmi_force_abort(kcs_bmc); + kcs_bmc->error = KCS_ILLEGAL_CONTROL_CODE; + break; + } +} + +int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc); +int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc) +{ + unsigned long flags; + int ret = -ENODATA; + u8 status; + + spin_lock_irqsave(&kcs_bmc->lock, flags); + + status = kcs_bmc_read_status(kcs_bmc); + if (status & KCS_STATUS_IBF) { + if (!kcs_bmc->running) + kcs_bmc_ipmi_force_abort(kcs_bmc); + else if (status & KCS_STATUS_CMD_DAT) + kcs_bmc_ipmi_handle_cmd(kcs_bmc); + else + kcs_bmc_ipmi_handle_data(kcs_bmc); + + ret = 0; + } + + spin_unlock_irqrestore(&kcs_bmc->lock, flags); + + return ret; +} +EXPORT_SYMBOL(kcs_bmc_ipmi_event); + +static inline struct kcs_bmc *to_kcs_bmc(struct file *filp) +{ + return container_of(filp->private_data, struct kcs_bmc, miscdev); +} + +static int kcs_bmc_ipmi_open(struct inode *inode, struct file *filp) +{ + struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + int ret = 0; + + spin_lock_irq(&kcs_bmc->lock); + if (!kcs_bmc->running) + kcs_bmc->running = 1; + else + ret = -EBUSY; + spin_unlock_irq(&kcs_bmc->lock); + + return ret; +} + +static __poll_t kcs_bmc_ipmi_poll(struct file *filp, poll_table *wait) +{ + struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + __poll_t mask = 0; + + poll_wait(filp, &kcs_bmc->queue, wait); + + spin_lock_irq(&kcs_bmc->lock); + if (kcs_bmc->data_in_avail) + mask |= EPOLLIN; + spin_unlock_irq(&kcs_bmc->lock); + + return mask; +} + +static ssize_t kcs_bmc_ipmi_read(struct file *filp, char __user *buf, + size_t count, loff_t *ppos) +{ + struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + bool data_avail; + size_t data_len; + ssize_t ret; + + if (!(filp->f_flags & O_NONBLOCK)) + wait_event_interruptible(kcs_bmc->queue, + kcs_bmc->data_in_avail); + + mutex_lock(&kcs_bmc->mutex); + + spin_lock_irq(&kcs_bmc->lock); + data_avail = kcs_bmc->data_in_avail; + if (data_avail) { + data_len = kcs_bmc->data_in_idx; + memcpy(kcs_bmc->kbuffer, kcs_bmc->data_in, data_len); + } + spin_unlock_irq(&kcs_bmc->lock); + + if (!data_avail) { + ret = -EAGAIN; + goto out_unlock; + } + + if (count < data_len) { + pr_err("channel=%u with too large data : %zu\n", + kcs_bmc->channel, data_len); + + spin_lock_irq(&kcs_bmc->lock); + kcs_bmc_ipmi_force_abort(kcs_bmc); + spin_unlock_irq(&kcs_bmc->lock); + + ret = -EOVERFLOW; + goto out_unlock; + } + + if (copy_to_user(buf, kcs_bmc->kbuffer, data_len)) { + ret = -EFAULT; + goto out_unlock; + } + + ret = data_len; + + spin_lock_irq(&kcs_bmc->lock); + if (kcs_bmc->phase == KCS_PHASE_WRITE_DONE) { + kcs_bmc->phase = KCS_PHASE_WAIT_READ; + kcs_bmc->data_in_avail = false; + kcs_bmc->data_in_idx = 0; + } else { + ret = -EAGAIN; + } + spin_unlock_irq(&kcs_bmc->lock); + +out_unlock: + mutex_unlock(&kcs_bmc->mutex); + + return ret; +} + +static ssize_t kcs_bmc_ipmi_write(struct file *filp, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + ssize_t ret; + + /* a minimum response size '3' : netfn + cmd + ccode */ + if (count < 3 || count > KCS_MSG_BUFSIZ) + return -EINVAL; + + mutex_lock(&kcs_bmc->mutex); + + if (copy_from_user(kcs_bmc->kbuffer, buf, count)) { + ret = -EFAULT; + goto out_unlock; + } + + spin_lock_irq(&kcs_bmc->lock); + if (kcs_bmc->phase == KCS_PHASE_WAIT_READ) { + kcs_bmc->phase = KCS_PHASE_READ; + kcs_bmc->data_out_idx = 1; + kcs_bmc->data_out_len = count; + memcpy(kcs_bmc->data_out, kcs_bmc->kbuffer, count); + kcs_bmc_write_data(kcs_bmc, kcs_bmc->data_out[0]); + ret = count; + } else { + ret = -EINVAL; + } + spin_unlock_irq(&kcs_bmc->lock); + +out_unlock: + mutex_unlock(&kcs_bmc->mutex); + + return ret; +} + +static long kcs_bmc_ipmi_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + long ret = 0; + + spin_lock_irq(&kcs_bmc->lock); + + switch (cmd) { + case IPMI_BMC_IOCTL_SET_SMS_ATN: + kcs_bmc_update_status(kcs_bmc, KCS_STATUS_SMS_ATN, KCS_STATUS_SMS_ATN); + break; + + case IPMI_BMC_IOCTL_CLEAR_SMS_ATN: + kcs_bmc_update_status(kcs_bmc, KCS_STATUS_SMS_ATN, 0); + break; + + case IPMI_BMC_IOCTL_FORCE_ABORT: + kcs_bmc_ipmi_force_abort(kcs_bmc); + break; + + default: + ret = -EINVAL; + break; + } + + spin_unlock_irq(&kcs_bmc->lock); + + return ret; +} + +static int kcs_bmc_ipmi_release(struct inode *inode, struct file *filp) +{ + struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + + spin_lock_irq(&kcs_bmc->lock); + kcs_bmc->running = 0; + kcs_bmc_ipmi_force_abort(kcs_bmc); + spin_unlock_irq(&kcs_bmc->lock); + + return 0; +} + +static const struct file_operations kcs_bmc_fops = { + .owner = THIS_MODULE, + .open = kcs_bmc_ipmi_open, + .read = kcs_bmc_ipmi_read, + .write = kcs_bmc_ipmi_write, + .release = kcs_bmc_ipmi_release, + .poll = kcs_bmc_ipmi_poll, + .unlocked_ioctl = kcs_bmc_ipmi_ioctl, +}; + +struct kcs_bmc *kcs_bmc_ipmi_alloc(struct device *dev, int sizeof_priv, u32 channel); +struct kcs_bmc *kcs_bmc_ipmi_alloc(struct device *dev, int sizeof_priv, u32 channel) +{ + struct kcs_bmc *kcs_bmc; + + kcs_bmc = devm_kzalloc(dev, sizeof(*kcs_bmc) + sizeof_priv, GFP_KERNEL); + if (!kcs_bmc) + return NULL; + + spin_lock_init(&kcs_bmc->lock); + kcs_bmc->channel = channel; + + mutex_init(&kcs_bmc->mutex); + init_waitqueue_head(&kcs_bmc->queue); + + kcs_bmc->data_in = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + kcs_bmc->data_out = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + kcs_bmc->kbuffer = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + + kcs_bmc->miscdev.minor = MISC_DYNAMIC_MINOR; + kcs_bmc->miscdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s%u", + DEVICE_NAME, channel); + if (!kcs_bmc->data_in || !kcs_bmc->data_out || !kcs_bmc->kbuffer || + !kcs_bmc->miscdev.name) + return NULL; + kcs_bmc->miscdev.fops = &kcs_bmc_fops; + + return kcs_bmc; +} +EXPORT_SYMBOL(kcs_bmc_ipmi_alloc); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Haiyue Wang "); +MODULE_DESCRIPTION("KCS BMC to handle the IPMI request from system software"); From patchwork Fri Mar 19 06:27:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455602 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=r9JDxkzM; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=G+gcrmhR; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vCC6RF7z9sWm for ; Fri, 19 Mar 2021 17:30:15 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234119AbhCSG3n (ORCPT ); Fri, 19 Mar 2021 02:29:43 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:49467 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234086AbhCSG3T (ORCPT ); Fri, 19 Mar 2021 02:29:19 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id EE23D580A7B; Fri, 19 Mar 2021 02:29:18 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:29:18 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=0tfn0jVZszKIo zkJKaOriclDoF/OY5PveWNZa9UgmYQ=; b=r9JDxkzMDQsrgcaeTXoZ8zhU0iETL HjsWF5VSL1QrbYg4sEGRpKBLC/jPHQe54bFemMGWscE2kxOMtBDoj6P61ZxTcSSQ fX7z2SL7thGZmm84K+o8Lwwxk9vYSLzeWs7muERtiAl1+2eKPipRiD8eqkCN965p JZO9H4qygf4PqXVLdPpflWDfr/cbC86nak9tea6Ke3kCXd9SuubMIgm7ne4ZkpAu 8VtmEU+377tXkHzbXl+vKD1tQ8Veo9ZreqCbX+Gx9VuMfjwkCRLHMGL9tCXWoVyl 4LgUFdyKl/Z+7kxfDlMsNPn6rXRZqbHGf7BylX9L1OYf32R201d8sSJeg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=0tfn0jVZszKIozkJKaOriclDoF/OY5PveWNZa9UgmYQ=; b=G+gcrmhR eL6hX3KQtOCu0/jdSXEeHZ6VoteyizN0Q3ruq2xUKbhgT9tYjQCQIrETGC1CwYsn ZvHxTKLdwnwBFDhpMFnmpPyIwofWWga6L9GtYCiIbkzf3vsTaAtTgoyjIINyN+vo VIimrqQsVbTC1iSaIIbdMjMBigVft79n046a1xZQ9nceUF1dQly4HMiw8s/R3WmZ Bo0ossCsgrkTOepen3D2U2swEgPNKVXzJ1Fk526hLMfWNVRIfr3R5qtm4MBeuYvF PS7gggNu9mBQf8IkRaA+QdesGzcZrsy7KPV/A5trLDaUzmhhj+8aTga097aaKf4R zPypSixyv1ffew== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppeduudekrddvuddtrddukedurdeh heenucevlhhushhtvghrufhiiigvpedunecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnh gurhgvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 5B9DB240057; Fri, 19 Mar 2021 02:29:13 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, chiawei_wang@aspeedtech.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 10/21] ipmi: kcs_bmc: Turn the driver data-structures inside-out Date: Fri, 19 Mar 2021 16:57:41 +1030 Message-Id: <20210319062752.145730-10-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Make the KCS device drivers responsible for allocating their own memory. Until now the private data for the device driver was allocated internal to the private data for the chardev interface. This coupling required the slightly awkward API of passing through the struct size for the driver private data to the chardev constructor, and then retrieving a pointer to the driver private data from the allocated chardev memory. In addition to being awkward, the arrangement prevents the implementation of alternative userspace interfaces as the device driver private data is not independent. Peel a layer off the onion and turn the data-structures inside out by exploiting container_of() and embedding `struct kcs_device` in the driver private data. Signed-off-by: Andrew Jeffery Reviewed-by: Zev Weiss --- drivers/char/ipmi/kcs_bmc.c | 15 +++++-- drivers/char/ipmi/kcs_bmc.h | 12 ++---- drivers/char/ipmi/kcs_bmc_aspeed.c | 60 ++++++++++++++++----------- drivers/char/ipmi/kcs_bmc_cdev_ipmi.c | 60 ++++++++++++++++++--------- drivers/char/ipmi/kcs_bmc_npcm7xx.c | 37 ++++++++++------- 5 files changed, 113 insertions(+), 71 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index ef5c48ffe74a..709b6bdec165 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -44,12 +44,19 @@ int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc) } EXPORT_SYMBOL(kcs_bmc_handle_event); -struct kcs_bmc *kcs_bmc_ipmi_alloc(struct device *dev, int sizeof_priv, u32 channel); -struct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv, u32 channel) +int kcs_bmc_ipmi_attach_cdev(struct kcs_bmc *kcs_bmc); +int kcs_bmc_add_device(struct kcs_bmc *kcs_bmc) { - return kcs_bmc_ipmi_alloc(dev, sizeof_priv, channel); + return kcs_bmc_ipmi_attach_cdev(kcs_bmc); } -EXPORT_SYMBOL(kcs_bmc_alloc); +EXPORT_SYMBOL(kcs_bmc_add_device); + +int kcs_bmc_ipmi_detach_cdev(struct kcs_bmc *kcs_bmc); +int kcs_bmc_remove_device(struct kcs_bmc *kcs_bmc) +{ + return kcs_bmc_ipmi_detach_cdev(kcs_bmc); +} +EXPORT_SYMBOL(kcs_bmc_remove_device); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Haiyue Wang "); diff --git a/drivers/char/ipmi/kcs_bmc.h b/drivers/char/ipmi/kcs_bmc.h index febea0c8deb4..bf0ae327997f 100644 --- a/drivers/char/ipmi/kcs_bmc.h +++ b/drivers/char/ipmi/kcs_bmc.h @@ -67,6 +67,8 @@ struct kcs_ioreg { }; struct kcs_bmc { + struct device *dev; + spinlock_t lock; u32 channel; @@ -94,17 +96,11 @@ struct kcs_bmc { u8 *kbuffer; struct miscdevice miscdev; - - unsigned long priv[]; }; -static inline void *kcs_bmc_priv(struct kcs_bmc *kcs_bmc) -{ - return kcs_bmc->priv; -} - int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc); -struct kcs_bmc *kcs_bmc_alloc(struct device *dev, int sizeof_priv, u32 channel); +int kcs_bmc_add_device(struct kcs_bmc *kcs_bmc); +int kcs_bmc_remove_device(struct kcs_bmc *kcs_bmc); u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc); void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data); diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 630cf095560e..0416ac78ce68 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -61,6 +61,8 @@ #define LPC_STR4 0x11C struct aspeed_kcs_bmc { + struct kcs_bmc kcs_bmc; + struct regmap *map; }; @@ -69,9 +71,14 @@ struct aspeed_kcs_of_ops { int (*get_io_address)(struct platform_device *pdev); }; +static inline struct aspeed_kcs_bmc *to_aspeed_kcs_bmc(struct kcs_bmc *kcs_bmc) +{ + return container_of(kcs_bmc, struct aspeed_kcs_bmc, kcs_bmc); +} + static u8 aspeed_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) { - struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); u32 val = 0; int rc; @@ -83,7 +90,7 @@ static u8 aspeed_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) static void aspeed_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) { - struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); int rc; rc = regmap_write(priv->map, reg, data); @@ -92,7 +99,7 @@ static void aspeed_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) static void aspeed_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val) { - struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); int rc; rc = regmap_update_bits(priv->map, reg, mask, val); @@ -114,7 +121,7 @@ static void aspeed_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val */ static void aspeed_kcs_set_address(struct kcs_bmc *kcs_bmc, u16 addr) { - struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); switch (kcs_bmc->channel) { case 1: @@ -148,7 +155,7 @@ static void aspeed_kcs_set_address(struct kcs_bmc *kcs_bmc, u16 addr) static void aspeed_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable) { - struct aspeed_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); switch (kcs_bmc->channel) { case 1: @@ -323,16 +330,16 @@ static int aspeed_kcs_of_v2_get_io_address(struct platform_device *pdev) static int aspeed_kcs_probe(struct platform_device *pdev) { const struct aspeed_kcs_of_ops *ops; - struct device *dev = &pdev->dev; + struct aspeed_kcs_bmc *priv; struct kcs_bmc *kcs_bmc; struct device_node *np; int rc, channel, addr; - np = dev->of_node->parent; + np = pdev->dev.of_node->parent; if (!of_device_is_compatible(np, "aspeed,ast2400-lpc-v2") && !of_device_is_compatible(np, "aspeed,ast2500-lpc-v2") && !of_device_is_compatible(np, "aspeed,ast2600-lpc-v2")) { - dev_err(dev, "unsupported LPC device binding\n"); + dev_err(&pdev->dev, "unsupported LPC device binding\n"); return -ENODEV; } ops = of_device_get_match_data(&pdev->dev); @@ -343,18 +350,27 @@ static int aspeed_kcs_probe(struct platform_device *pdev) if (channel < 0) return channel; - kcs_bmc = kcs_bmc_alloc(&pdev->dev, sizeof(struct aspeed_kcs_bmc), channel); - if (!kcs_bmc) + addr = ops->get_io_address(pdev); + if (addr < 0) + return addr; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) return -ENOMEM; + kcs_bmc = &priv->kcs_bmc; + kcs_bmc->dev = &pdev->dev; + kcs_bmc->channel = channel; kcs_bmc->ioreg = ast_kcs_bmc_ioregs[channel - 1]; kcs_bmc->io_inputb = aspeed_kcs_inb; kcs_bmc->io_outputb = aspeed_kcs_outb; kcs_bmc->io_updateb = aspeed_kcs_updateb; - addr = ops->get_io_address(pdev); - if (addr < 0) - return addr; + priv->map = syscon_node_to_regmap(pdev->dev.parent->of_node); + if (IS_ERR(priv->map)) { + dev_err(&pdev->dev, "Couldn't get regmap\n"); + return -ENODEV; + } aspeed_kcs_set_address(kcs_bmc, addr); @@ -362,29 +378,25 @@ static int aspeed_kcs_probe(struct platform_device *pdev) if (rc) return rc; - dev_set_drvdata(dev, kcs_bmc); + platform_set_drvdata(pdev, priv); aspeed_kcs_enable_channel(kcs_bmc, true); - rc = misc_register(&kcs_bmc->miscdev); - if (rc) { - dev_err(dev, "Unable to register device\n"); + rc = kcs_bmc_add_device(&priv->kcs_bmc); + if (rc < 0) return rc; - } - dev_dbg(&pdev->dev, - "Probed KCS device %d (IDR=0x%x, ODR=0x%x, STR=0x%x)\n", - kcs_bmc->channel, kcs_bmc->ioreg.idr, kcs_bmc->ioreg.odr, - kcs_bmc->ioreg.str); + dev_info(&pdev->dev, "Initialised channel %d at 0x%x\n", kcs_bmc->channel, addr); return 0; } static int aspeed_kcs_remove(struct platform_device *pdev) { - struct kcs_bmc *kcs_bmc = dev_get_drvdata(&pdev->dev); + struct aspeed_kcs_bmc *priv = platform_get_drvdata(pdev); + struct kcs_bmc *kcs_bmc = &priv->kcs_bmc; - misc_deregister(&kcs_bmc->miscdev); + kcs_bmc_remove_device(kcs_bmc); return 0; } diff --git a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c index 82c77994e481..0ca71c135a1a 100644 --- a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c +++ b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c @@ -382,7 +382,7 @@ static int kcs_bmc_ipmi_release(struct inode *inode, struct file *filp) return 0; } -static const struct file_operations kcs_bmc_fops = { +static const struct file_operations kcs_bmc_ipmi_fops = { .owner = THIS_MODULE, .open = kcs_bmc_ipmi_open, .read = kcs_bmc_ipmi_read, @@ -392,36 +392,58 @@ static const struct file_operations kcs_bmc_fops = { .unlocked_ioctl = kcs_bmc_ipmi_ioctl, }; -struct kcs_bmc *kcs_bmc_ipmi_alloc(struct device *dev, int sizeof_priv, u32 channel); -struct kcs_bmc *kcs_bmc_ipmi_alloc(struct device *dev, int sizeof_priv, u32 channel) +int kcs_bmc_ipmi_attach_cdev(struct kcs_bmc *kcs_bmc); +int kcs_bmc_ipmi_attach_cdev(struct kcs_bmc *kcs_bmc) { - struct kcs_bmc *kcs_bmc; - - kcs_bmc = devm_kzalloc(dev, sizeof(*kcs_bmc) + sizeof_priv, GFP_KERNEL); - if (!kcs_bmc) - return NULL; + int rc; spin_lock_init(&kcs_bmc->lock); - kcs_bmc->channel = channel; - mutex_init(&kcs_bmc->mutex); init_waitqueue_head(&kcs_bmc->queue); - kcs_bmc->data_in = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); - kcs_bmc->data_out = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); - kcs_bmc->kbuffer = devm_kmalloc(dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + kcs_bmc->data_in = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + kcs_bmc->data_out = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + kcs_bmc->kbuffer = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); kcs_bmc->miscdev.minor = MISC_DYNAMIC_MINOR; - kcs_bmc->miscdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s%u", - DEVICE_NAME, channel); + kcs_bmc->miscdev.name = devm_kasprintf(kcs_bmc->dev, GFP_KERNEL, "%s%u", + DEVICE_NAME, kcs_bmc->channel); if (!kcs_bmc->data_in || !kcs_bmc->data_out || !kcs_bmc->kbuffer || !kcs_bmc->miscdev.name) - return NULL; - kcs_bmc->miscdev.fops = &kcs_bmc_fops; + return -ENOMEM; - return kcs_bmc; + kcs_bmc->miscdev.fops = &kcs_bmc_ipmi_fops; + + rc = misc_register(&kcs_bmc->miscdev); + if (rc) { + dev_err(kcs_bmc->dev, "Unable to register device: %d\n", rc); + return rc; + } + + dev_info(kcs_bmc->dev, "Initialised IPMI client for channel %d", kcs_bmc->channel); + + return 0; +} +EXPORT_SYMBOL(kcs_bmc_ipmi_attach_cdev); + +int kcs_bmc_ipmi_detach_cdev(struct kcs_bmc *kcs_bmc); +int kcs_bmc_ipmi_detach_cdev(struct kcs_bmc *kcs_bmc) +{ + misc_deregister(&kcs_bmc->miscdev); + + spin_lock_irq(&kcs_bmc->lock); + kcs_bmc->running = 0; + kcs_bmc_ipmi_force_abort(kcs_bmc); + spin_unlock_irq(&kcs_bmc->lock); + + devm_kfree(kcs_bmc->dev, kcs_bmc->kbuffer); + devm_kfree(kcs_bmc->dev, kcs_bmc->data_out); + devm_kfree(kcs_bmc->dev, kcs_bmc->data_in); + devm_kfree(kcs_bmc->dev, kcs_bmc); + + return 0; } -EXPORT_SYMBOL(kcs_bmc_ipmi_alloc); +EXPORT_SYMBOL(kcs_bmc_ipmi_detach_cdev); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Haiyue Wang "); diff --git a/drivers/char/ipmi/kcs_bmc_npcm7xx.c b/drivers/char/ipmi/kcs_bmc_npcm7xx.c index 1f44aadec9e8..5d017498dc69 100644 --- a/drivers/char/ipmi/kcs_bmc_npcm7xx.c +++ b/drivers/char/ipmi/kcs_bmc_npcm7xx.c @@ -65,6 +65,8 @@ struct npcm7xx_kcs_reg { }; struct npcm7xx_kcs_bmc { + struct kcs_bmc kcs_bmc; + struct regmap *map; const struct npcm7xx_kcs_reg *reg; @@ -76,9 +78,14 @@ static const struct npcm7xx_kcs_reg npcm7xx_kcs_reg_tbl[KCS_CHANNEL_MAX] = { { .sts = KCS3ST, .dob = KCS3DO, .dib = KCS3DI, .ctl = KCS3CTL, .ie = KCS3IE }, }; +static inline struct npcm7xx_kcs_bmc *to_npcm7xx_kcs_bmc(struct kcs_bmc *kcs_bmc) +{ + return container_of(kcs_bmc, struct npcm7xx_kcs_bmc, kcs_bmc); +} + static u8 npcm7xx_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) { - struct npcm7xx_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); u32 val = 0; int rc; @@ -90,7 +97,7 @@ static u8 npcm7xx_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) static void npcm7xx_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) { - struct npcm7xx_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); int rc; rc = regmap_write(priv->map, reg, data); @@ -99,7 +106,7 @@ static void npcm7xx_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) static void npcm7xx_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 data) { - struct npcm7xx_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); int rc; rc = regmap_update_bits(priv->map, reg, mask, data); @@ -108,7 +115,7 @@ static void npcm7xx_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 da static void npcm7xx_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable) { - struct npcm7xx_kcs_bmc *priv = kcs_bmc_priv(kcs_bmc); + struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); regmap_update_bits(priv->map, priv->reg->ctl, KCS_CTL_IBFIE, enable ? KCS_CTL_IBFIE : 0); @@ -155,11 +162,10 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) return -ENODEV; } - kcs_bmc = kcs_bmc_alloc(dev, sizeof(*priv), chan); - if (!kcs_bmc) + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) return -ENOMEM; - priv = kcs_bmc_priv(kcs_bmc); priv->map = syscon_node_to_regmap(dev->parent->of_node); if (IS_ERR(priv->map)) { dev_err(dev, "Couldn't get regmap\n"); @@ -167,6 +173,9 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) } priv->reg = &npcm7xx_kcs_reg_tbl[chan - 1]; + kcs_bmc = &priv->kcs_bmc; + kcs_bmc->dev = &pdev->dev; + kcs_bmc->channel = chan; kcs_bmc->ioreg.idr = priv->reg->dib; kcs_bmc->ioreg.odr = priv->reg->dob; kcs_bmc->ioreg.str = priv->reg->sts; @@ -174,31 +183,27 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) kcs_bmc->io_outputb = npcm7xx_kcs_outb; kcs_bmc->io_updateb = npcm7xx_kcs_updateb; - dev_set_drvdata(dev, kcs_bmc); + platform_set_drvdata(pdev, priv); npcm7xx_kcs_enable_channel(kcs_bmc, true); rc = npcm7xx_kcs_config_irq(kcs_bmc, pdev); if (rc) return rc; - rc = misc_register(&kcs_bmc->miscdev); - if (rc) { - dev_err(dev, "Unable to register device\n"); - return rc; - } pr_info("channel=%u idr=0x%x odr=0x%x str=0x%x\n", chan, kcs_bmc->ioreg.idr, kcs_bmc->ioreg.odr, kcs_bmc->ioreg.str); - return 0; + return kcs_bmc_add_device(kcs_bmc); } static int npcm7xx_kcs_remove(struct platform_device *pdev) { - struct kcs_bmc *kcs_bmc = dev_get_drvdata(&pdev->dev); + struct npcm7xx_kcs_bmc *priv = platform_get_drvdata(pdev); + struct kcs_bmc *kcs_bmc = &priv->kcs_bmc; - misc_deregister(&kcs_bmc->miscdev); + kcs_bmc_remove_device(kcs_bmc); return 0; } From patchwork Fri Mar 19 06:27:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455601 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=Pf8hGy/z; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=Vh1IrRzx; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vCC0hyjz9sW1 for ; Fri, 19 Mar 2021 17:30:15 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234049AbhCSG3o (ORCPT ); Fri, 19 Mar 2021 02:29:44 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:40183 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234034AbhCSG3Z (ORCPT ); Fri, 19 Mar 2021 02:29:25 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id E701E580A7D; Fri, 19 Mar 2021 02:29:24 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:29:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=yux2JxItyAnZD iFpMj0SQrm/I4fD6z4OVPwlycRVY1w=; b=Pf8hGy/z+l6Lo5+eY/ueQAOVx3fXf SO55GGy1qJv3nzzO8wH0mjgHCm3QCrvu/+51FOrWQOVHAwTr5IhmuDRVz2ZO5AJj JwiD1GW+0JbVhr9uawpF4Wzd4P4IljdOKjuUUkkIUKPLUfuSBrVDDiisZ463HoBz g3FYuRjhQoUJ2IWRPEX/OxOhKFmjyVMdzhU68RjsDUsVW58m8mIzQr08Px4a9KYh 94R+hccXw+EMeQWI3tNOdby8rPUCiXCSvnsdhlKg4jroOCulpUUVoECh62B0Ob7A CdckWeELxVfTbb14aviCLFwBkmQiDPyYhi7s5rhht60f2pXuPwB0lICUg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=yux2JxItyAnZDiFpMj0SQrm/I4fD6z4OVPwlycRVY1w=; b=Vh1IrRzx CP+Ceh1fYGiSmp6T/lpeLb+jjoCpCTfinFEHac0Nh8iwqrkfarn2a2StQ8XpILO3 xe2VjajYDxIknbW4RbngEdSUHzOPh9Kw5jTTHoQ3jlr17JVo/F/DQXZVdi7WmZCX R7oNhN4Dx5qqnc7HOyJyyl1jcM9GqKgHm/Amt0YSyy11AXHWMwccP3gzmMncDa5N vNQJft6hlKk7GUeA0HDdxtArMkOtuYACDjJMpPuzwAwHs5eYOLUYRahjV4DBJhs8 48lSzzPCrTuGHOlJvyWTt9kBmmmUD/x+DiHXqSncYtg001NqtoTIHdTVsrl1VHSn NmAuS+u2/s636Q== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppeduudekrddvuddtrddukedurdeh heenucevlhhushhtvghrufhiiigvpedvnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnh gurhgvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 5426B240057; Fri, 19 Mar 2021 02:29:19 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, chiawei_wang@aspeedtech.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 11/21] ipmi: kcs_bmc: Split headers into device and client Date: Fri, 19 Mar 2021 16:57:42 +1030 Message-Id: <20210319062752.145730-11-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Strengthen the distinction between code that abstracts the implementation of the KCS behaviours (device drivers) and code that exploits KCS behaviours (clients). Neither needs to know about the APIs required by the other, so provide separate headers. Signed-off-by: Andrew Jeffery --- drivers/char/ipmi/kcs_bmc.c | 21 ++++++++++----- drivers/char/ipmi/kcs_bmc.h | 30 ++++++++++----------- drivers/char/ipmi/kcs_bmc_aspeed.c | 20 +++++++++----- drivers/char/ipmi/kcs_bmc_cdev_ipmi.c | 39 ++++++++++++++++++--------- drivers/char/ipmi/kcs_bmc_client.h | 29 ++++++++++++++++++++ drivers/char/ipmi/kcs_bmc_device.h | 19 +++++++++++++ drivers/char/ipmi/kcs_bmc_npcm7xx.c | 20 +++++++++----- 7 files changed, 129 insertions(+), 49 deletions(-) create mode 100644 drivers/char/ipmi/kcs_bmc_client.h create mode 100644 drivers/char/ipmi/kcs_bmc_device.h diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index 709b6bdec165..1046ce2bbefc 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -1,46 +1,52 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2015-2018, Intel Corporation. + * Copyright (c) 2021, IBM Corp. */ #include #include "kcs_bmc.h" +/* Implement both the device and client interfaces here */ +#include "kcs_bmc_device.h" +#include "kcs_bmc_client.h" + +/* Consumer data access */ + u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc) { - return kcs_bmc->io_inputb(kcs_bmc, kcs_bmc->ioreg.idr); + return kcs_bmc->ops->io_inputb(kcs_bmc, kcs_bmc->ioreg.idr); } EXPORT_SYMBOL(kcs_bmc_read_data); void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data) { - kcs_bmc->io_outputb(kcs_bmc, kcs_bmc->ioreg.odr, data); + kcs_bmc->ops->io_outputb(kcs_bmc, kcs_bmc->ioreg.odr, data); } EXPORT_SYMBOL(kcs_bmc_write_data); u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc) { - return kcs_bmc->io_inputb(kcs_bmc, kcs_bmc->ioreg.str); + return kcs_bmc->ops->io_inputb(kcs_bmc, kcs_bmc->ioreg.str); } EXPORT_SYMBOL(kcs_bmc_read_status); void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data) { - kcs_bmc->io_outputb(kcs_bmc, kcs_bmc->ioreg.str, data); + kcs_bmc->ops->io_outputb(kcs_bmc, kcs_bmc->ioreg.str, data); } EXPORT_SYMBOL(kcs_bmc_write_status); void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val) { - kcs_bmc->io_updateb(kcs_bmc, kcs_bmc->ioreg.str, mask, val); + kcs_bmc->ops->io_updateb(kcs_bmc, kcs_bmc->ioreg.str, mask, val); } EXPORT_SYMBOL(kcs_bmc_update_status); -int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc); int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc) { - return kcs_bmc_ipmi_event(kcs_bmc); + return kcs_bmc->client.ops->event(&kcs_bmc->client); } EXPORT_SYMBOL(kcs_bmc_handle_event); @@ -60,4 +66,5 @@ EXPORT_SYMBOL(kcs_bmc_remove_device); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Haiyue Wang "); +MODULE_AUTHOR("Andrew Jeffery "); MODULE_DESCRIPTION("KCS BMC to handle the IPMI request from system software"); diff --git a/drivers/char/ipmi/kcs_bmc.h b/drivers/char/ipmi/kcs_bmc.h index bf0ae327997f..a1350e567723 100644 --- a/drivers/char/ipmi/kcs_bmc.h +++ b/drivers/char/ipmi/kcs_bmc.h @@ -8,6 +8,15 @@ #include +#include "kcs_bmc_client.h" + +#define KCS_BMC_EVENT_NONE 0 +#define KCS_BMC_EVENT_HANDLED 1 + +#define KCS_BMC_STR_OBF BIT(0) +#define KCS_BMC_STR_IBF BIT(1) +#define KCS_BMC_STR_CMD_DAT BIT(3) + /* Different phases of the KCS BMC module. * KCS_PHASE_IDLE: * BMC should not be expecting nor sending any data. @@ -66,19 +75,21 @@ struct kcs_ioreg { u32 str; }; +struct kcs_bmc_device_ops; + struct kcs_bmc { struct device *dev; + const struct kcs_bmc_device_ops *ops; + + struct kcs_bmc_client client; + spinlock_t lock; u32 channel; int running; - /* Setup by BMC KCS controller driver */ struct kcs_ioreg ioreg; - u8 (*io_inputb)(struct kcs_bmc *kcs_bmc, u32 reg); - void (*io_outputb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 b); - void (*io_updateb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val); enum kcs_phases phase; enum kcs_errors error; @@ -97,15 +108,4 @@ struct kcs_bmc { struct miscdevice miscdev; }; - -int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc); -int kcs_bmc_add_device(struct kcs_bmc *kcs_bmc); -int kcs_bmc_remove_device(struct kcs_bmc *kcs_bmc); - -u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc); -void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data); -u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc); -void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data); -void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val); - #endif /* __KCS_BMC_H__ */ diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 0416ac78ce68..1b313355b1c8 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -21,7 +21,7 @@ #include #include -#include "kcs_bmc.h" +#include "kcs_bmc_device.h" #define DEVICE_NAME "ast-kcs-bmc" @@ -220,14 +220,22 @@ static void aspeed_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable) } } +static const struct kcs_bmc_device_ops aspeed_kcs_ops = { + .io_inputb = aspeed_kcs_inb, + .io_outputb = aspeed_kcs_outb, + .io_updateb = aspeed_kcs_updateb, +}; + static irqreturn_t aspeed_kcs_irq(int irq, void *arg) { struct kcs_bmc *kcs_bmc = arg; + int rc; - if (!kcs_bmc_handle_event(kcs_bmc)) - return IRQ_HANDLED; + rc = kcs_bmc_handle_event(kcs_bmc); + if (rc < 0) + dev_warn(kcs_bmc->dev, "Failed to service irq: %d\n", rc); - return IRQ_NONE; + return rc == KCS_BMC_EVENT_HANDLED ? IRQ_HANDLED : IRQ_NONE; } static int aspeed_kcs_config_irq(struct kcs_bmc *kcs_bmc, @@ -362,9 +370,7 @@ static int aspeed_kcs_probe(struct platform_device *pdev) kcs_bmc->dev = &pdev->dev; kcs_bmc->channel = channel; kcs_bmc->ioreg = ast_kcs_bmc_ioregs[channel - 1]; - kcs_bmc->io_inputb = aspeed_kcs_inb; - kcs_bmc->io_outputb = aspeed_kcs_outb; - kcs_bmc->io_updateb = aspeed_kcs_updateb; + kcs_bmc->ops = &aspeed_kcs_ops; priv->map = syscon_node_to_regmap(pdev->dev.parent->of_node); if (IS_ERR(priv->map)) { diff --git a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c index 0ca71c135a1a..fd852d8abe48 100644 --- a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c +++ b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c @@ -22,7 +22,6 @@ #define KCS_ZERO_DATA 0 - /* IPMI 2.0 - Table 9-1, KCS Interface Status Register Bits */ #define KCS_STATUS_STATE(state) (state << 6) #define KCS_STATUS_STATE_MASK GENMASK(7, 6) @@ -179,12 +178,19 @@ static void kcs_bmc_ipmi_handle_cmd(struct kcs_bmc *kcs_bmc) } } -int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc); -int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc) +static inline struct kcs_bmc *client_to_kcs_bmc(struct kcs_bmc_client *client) { + return container_of(client, struct kcs_bmc, client); +} + +static int kcs_bmc_ipmi_event(struct kcs_bmc_client *client) +{ + struct kcs_bmc *kcs_bmc; unsigned long flags; - int ret = -ENODATA; u8 status; + int ret; + + kcs_bmc = client_to_kcs_bmc(client); spin_lock_irqsave(&kcs_bmc->lock, flags); @@ -197,23 +203,28 @@ int kcs_bmc_ipmi_event(struct kcs_bmc *kcs_bmc) else kcs_bmc_ipmi_handle_data(kcs_bmc); - ret = 0; + ret = KCS_BMC_EVENT_HANDLED; + } else { + ret = KCS_BMC_EVENT_NONE; } spin_unlock_irqrestore(&kcs_bmc->lock, flags); return ret; } -EXPORT_SYMBOL(kcs_bmc_ipmi_event); -static inline struct kcs_bmc *to_kcs_bmc(struct file *filp) +static const struct kcs_bmc_client_ops kcs_bmc_ipmi_client_ops = { + .event = kcs_bmc_ipmi_event, +}; + +static inline struct kcs_bmc *file_to_kcs_bmc(struct file *filp) { return container_of(filp->private_data, struct kcs_bmc, miscdev); } static int kcs_bmc_ipmi_open(struct inode *inode, struct file *filp) { - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); int ret = 0; spin_lock_irq(&kcs_bmc->lock); @@ -228,7 +239,7 @@ static int kcs_bmc_ipmi_open(struct inode *inode, struct file *filp) static __poll_t kcs_bmc_ipmi_poll(struct file *filp, poll_table *wait) { - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); __poll_t mask = 0; poll_wait(filp, &kcs_bmc->queue, wait); @@ -244,7 +255,7 @@ static __poll_t kcs_bmc_ipmi_poll(struct file *filp, poll_table *wait) static ssize_t kcs_bmc_ipmi_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); bool data_avail; size_t data_len; ssize_t ret; @@ -306,7 +317,7 @@ static ssize_t kcs_bmc_ipmi_read(struct file *filp, char __user *buf, static ssize_t kcs_bmc_ipmi_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); ssize_t ret; /* a minimum response size '3' : netfn + cmd + ccode */ @@ -342,7 +353,7 @@ static ssize_t kcs_bmc_ipmi_write(struct file *filp, const char __user *buf, static long kcs_bmc_ipmi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); long ret = 0; spin_lock_irq(&kcs_bmc->lock); @@ -372,7 +383,7 @@ static long kcs_bmc_ipmi_ioctl(struct file *filp, unsigned int cmd, static int kcs_bmc_ipmi_release(struct inode *inode, struct file *filp) { - struct kcs_bmc *kcs_bmc = to_kcs_bmc(filp); + struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); spin_lock_irq(&kcs_bmc->lock); kcs_bmc->running = 0; @@ -401,6 +412,8 @@ int kcs_bmc_ipmi_attach_cdev(struct kcs_bmc *kcs_bmc) mutex_init(&kcs_bmc->mutex); init_waitqueue_head(&kcs_bmc->queue); + kcs_bmc->client.dev = kcs_bmc; + kcs_bmc->client.ops = &kcs_bmc_ipmi_client_ops; kcs_bmc->data_in = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); kcs_bmc->data_out = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); kcs_bmc->kbuffer = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); diff --git a/drivers/char/ipmi/kcs_bmc_client.h b/drivers/char/ipmi/kcs_bmc_client.h new file mode 100644 index 000000000000..140631d157d8 --- /dev/null +++ b/drivers/char/ipmi/kcs_bmc_client.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021, IBM Corp. */ + +#ifndef __KCS_BMC_CONSUMER_H__ +#define __KCS_BMC_CONSUMER_H__ + +#include +#include +#include + +struct kcs_bmc; +struct kcs_bmc_client_ops; + +struct kcs_bmc_client { + const struct kcs_bmc_client_ops *ops; + + struct kcs_bmc *dev; +}; + +struct kcs_bmc_client_ops { + int (*event)(struct kcs_bmc_client *client); +}; + +u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc); +void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data); +u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc); +void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data); +void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val); +#endif diff --git a/drivers/char/ipmi/kcs_bmc_device.h b/drivers/char/ipmi/kcs_bmc_device.h new file mode 100644 index 000000000000..33462174516d --- /dev/null +++ b/drivers/char/ipmi/kcs_bmc_device.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2021, IBM Corp. */ + +#ifndef __KCS_BMC_DEVICE_H__ +#define __KCS_BMC_DEVICE_H__ + +#include "kcs_bmc.h" + +struct kcs_bmc_device_ops { + u8 (*io_inputb)(struct kcs_bmc *kcs_bmc, u32 reg); + void (*io_outputb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 b); + void (*io_updateb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 b); +}; + +int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc); +int kcs_bmc_add_device(struct kcs_bmc *kcs_bmc); +int kcs_bmc_remove_device(struct kcs_bmc *kcs_bmc); + +#endif diff --git a/drivers/char/ipmi/kcs_bmc_npcm7xx.c b/drivers/char/ipmi/kcs_bmc_npcm7xx.c index 5d017498dc69..1d21697fc585 100644 --- a/drivers/char/ipmi/kcs_bmc_npcm7xx.c +++ b/drivers/char/ipmi/kcs_bmc_npcm7xx.c @@ -17,7 +17,7 @@ #include #include -#include "kcs_bmc.h" +#include "kcs_bmc_device.h" #define DEVICE_NAME "npcm-kcs-bmc" #define KCS_CHANNEL_MAX 3 @@ -127,11 +127,13 @@ static void npcm7xx_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable) static irqreturn_t npcm7xx_kcs_irq(int irq, void *arg) { struct kcs_bmc *kcs_bmc = arg; + int rc; - if (!kcs_bmc_handle_event(kcs_bmc)) - return IRQ_HANDLED; + rc = kcs_bmc_handle_event(kcs_bmc); + if (rc < 0) + dev_warn(kcs_bmc->dev, "Failed to service irq: %d\n", rc); - return IRQ_NONE; + return rc == KCS_BMC_EVENT_HANDLED ? IRQ_HANDLED : IRQ_NONE; } static int npcm7xx_kcs_config_irq(struct kcs_bmc *kcs_bmc, @@ -148,6 +150,12 @@ static int npcm7xx_kcs_config_irq(struct kcs_bmc *kcs_bmc, dev_name(dev), kcs_bmc); } +static const struct kcs_bmc_device_ops npcm7xx_kcs_ops = { + .io_inputb = npcm7xx_kcs_inb, + .io_outputb = npcm7xx_kcs_outb, + .io_updateb = npcm7xx_kcs_updateb, +}; + static int npcm7xx_kcs_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -179,9 +187,7 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) kcs_bmc->ioreg.idr = priv->reg->dib; kcs_bmc->ioreg.odr = priv->reg->dob; kcs_bmc->ioreg.str = priv->reg->sts; - kcs_bmc->io_inputb = npcm7xx_kcs_inb; - kcs_bmc->io_outputb = npcm7xx_kcs_outb; - kcs_bmc->io_updateb = npcm7xx_kcs_updateb; + kcs_bmc->ops = &npcm7xx_kcs_ops; platform_set_drvdata(pdev, priv); From patchwork Fri Mar 19 06:27:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455606 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=ddZqYvEY; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=Qo83C1Hq; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vCP1WkFz9sVS for ; Fri, 19 Mar 2021 17:30:25 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234074AbhCSG3p (ORCPT ); Fri, 19 Mar 2021 02:29:45 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:38491 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234033AbhCSG3b (ORCPT ); Fri, 19 Mar 2021 02:29:31 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id E9EA0580A7F; Fri, 19 Mar 2021 02:29:30 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:29:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=MOKXbd8nHMwCj hlTVHhTtPz0m7OeJgpSBVk+I1P+FVU=; b=ddZqYvEY6CPFhRm6sWDtUanuPvtHp ZevBI7Ss5YRKt8ecYj4pl3wVtCDJFwuulbYSFD9J3TYB+GD0vjFrK98T6qxxSwoC IaG8rC66n3tj0LXBqvuNccyNQNawrh27WUmKQPmC0tKQhX7b8uMVmITC3z/FrnuV T9fDoHbofkJlKZmwRXSESij4R5Qrh+HAfPsspKLXkVwYYoCvhxHI+JB6FGhUVg7p KC7AzKDKPe0j2JJBuFVaex8bQEsln8imz22rlqizeVVebVkYPNFFlX4Chy/iWsro z15xxhsEWH4z9gsTWIrwXY4LixKPJE8RdgF7ctx1ZDSr5g3QSRoE3JmFQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=MOKXbd8nHMwCjhlTVHhTtPz0m7OeJgpSBVk+I1P+FVU=; b=Qo83C1Hq qgI3fcM/9qt0XkoLj8IM/S0BYFGAL/f4nrGh/u0BvEPdlYViSq6AacLV9idlOfJJ g6sr6MfRr3eT4XgeF0pWwhPG/5xt3QzmVn2DwVsUnF/uGuUBsYHdEIK03vLEVkPp 3zGieM9kXziBHLMd5cyvgc4x6gknNGT6KYt1MVh4Nl3eK35uAL0s2oaJdpVFL7Fq /wa/E0LVEZSgmRWzHWOa2KTzDEuIV7pSYClogMMPJEudA0okD0zJQ9sR8Ns7PMxz UEmWb3ksE/n5uMHvwOzIF49hREv9DJ5d0EJb+a80mbsoEwFa5qC4Pj7L4uhMa9/U pKtCz/+evJg2Kw== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppeduudekrddvuddtrddukedurdeh heenucevlhhushhtvghrufhiiigvpeefnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnh gurhgvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 5194724005B; Fri, 19 Mar 2021 02:29:25 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, chiawei_wang@aspeedtech.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 12/21] ipmi: kcs_bmc: Strip private client data from struct kcs_bmc Date: Fri, 19 Mar 2021 16:57:43 +1030 Message-Id: <20210319062752.145730-12-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Move all client-private data out of `struct kcs_bmc` into the KCS client implementation. With this change the KCS BMC core code now only concerns itself with abstract `struct kcs_bmc` and `struct kcs_bmc_client` types, achieving expected separation of concerns. Further, the change clears the path for implementation of alternative userspace interfaces. The chardev data-structures are rearranged in the same manner applied to the KCS device driver data-structures in an earlier patch - `struct kcs_bmc_client` is embedded in the client's private data and we exploit container_of() to translate as required. Finally, now that it is free of client data, `struct kcs_bmc` is renamed to `struct kcs_bmc_device` to contrast `struct kcs_bmc_client`. Signed-off-by: Andrew Jeffery --- drivers/char/ipmi/kcs_bmc.c | 68 +++- drivers/char/ipmi/kcs_bmc.h | 86 +----- drivers/char/ipmi/kcs_bmc_aspeed.c | 22 +- drivers/char/ipmi/kcs_bmc_cdev_ipmi.c | 428 ++++++++++++++++---------- drivers/char/ipmi/kcs_bmc_client.h | 28 +- drivers/char/ipmi/kcs_bmc_device.h | 12 +- drivers/char/ipmi/kcs_bmc_npcm7xx.c | 20 +- 7 files changed, 368 insertions(+), 296 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index 1046ce2bbefc..266ebec71d6f 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -4,6 +4,7 @@ * Copyright (c) 2021, IBM Corp. */ +#include #include #include "kcs_bmc.h" @@ -14,51 +15,96 @@ /* Consumer data access */ -u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc) +u8 kcs_bmc_read_data(struct kcs_bmc_device *kcs_bmc) { return kcs_bmc->ops->io_inputb(kcs_bmc, kcs_bmc->ioreg.idr); } EXPORT_SYMBOL(kcs_bmc_read_data); -void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data) +void kcs_bmc_write_data(struct kcs_bmc_device *kcs_bmc, u8 data) { kcs_bmc->ops->io_outputb(kcs_bmc, kcs_bmc->ioreg.odr, data); } EXPORT_SYMBOL(kcs_bmc_write_data); -u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc) +u8 kcs_bmc_read_status(struct kcs_bmc_device *kcs_bmc) { return kcs_bmc->ops->io_inputb(kcs_bmc, kcs_bmc->ioreg.str); } EXPORT_SYMBOL(kcs_bmc_read_status); -void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data) +void kcs_bmc_write_status(struct kcs_bmc_device *kcs_bmc, u8 data) { kcs_bmc->ops->io_outputb(kcs_bmc, kcs_bmc->ioreg.str, data); } EXPORT_SYMBOL(kcs_bmc_write_status); -void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val) +void kcs_bmc_update_status(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 val) { kcs_bmc->ops->io_updateb(kcs_bmc, kcs_bmc->ioreg.str, mask, val); } EXPORT_SYMBOL(kcs_bmc_update_status); -int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc) +int kcs_bmc_handle_event(struct kcs_bmc_device *kcs_bmc) { - return kcs_bmc->client.ops->event(&kcs_bmc->client); + struct kcs_bmc_client *client; + int rc; + + spin_lock(&kcs_bmc->lock); + client = kcs_bmc->client; + if (client) { + rc = client->ops->event(client); + } else { + u8 status; + + status = kcs_bmc_read_status(kcs_bmc); + if (status & KCS_BMC_STR_IBF) { + /* Ack the event by reading the data */ + kcs_bmc_read_data(kcs_bmc); + rc = KCS_BMC_EVENT_HANDLED; + } else { + rc = KCS_BMC_EVENT_NONE; + } + } + spin_unlock(&kcs_bmc->lock); + + return rc; } EXPORT_SYMBOL(kcs_bmc_handle_event); -int kcs_bmc_ipmi_attach_cdev(struct kcs_bmc *kcs_bmc); -int kcs_bmc_add_device(struct kcs_bmc *kcs_bmc) +int kcs_bmc_enable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client) +{ + int rc; + + spin_lock_irq(&kcs_bmc->lock); + if (kcs_bmc->client) { + rc = -EBUSY; + } else { + kcs_bmc->client = client; + rc = 0; + } + spin_unlock_irq(&kcs_bmc->lock); + + return rc; +} +EXPORT_SYMBOL(kcs_bmc_enable_device); + +void kcs_bmc_disable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client) +{ + spin_lock_irq(&kcs_bmc->lock); + if (client == kcs_bmc->client) + kcs_bmc->client = NULL; + spin_unlock_irq(&kcs_bmc->lock); +} +EXPORT_SYMBOL(kcs_bmc_disable_device); + +int kcs_bmc_add_device(struct kcs_bmc_device *kcs_bmc) { return kcs_bmc_ipmi_attach_cdev(kcs_bmc); } EXPORT_SYMBOL(kcs_bmc_add_device); -int kcs_bmc_ipmi_detach_cdev(struct kcs_bmc *kcs_bmc); -int kcs_bmc_remove_device(struct kcs_bmc *kcs_bmc) +int kcs_bmc_remove_device(struct kcs_bmc_device *kcs_bmc) { return kcs_bmc_ipmi_detach_cdev(kcs_bmc); } diff --git a/drivers/char/ipmi/kcs_bmc.h b/drivers/char/ipmi/kcs_bmc.h index a1350e567723..3f266740c759 100644 --- a/drivers/char/ipmi/kcs_bmc.h +++ b/drivers/char/ipmi/kcs_bmc.h @@ -6,9 +6,7 @@ #ifndef __KCS_BMC_H__ #define __KCS_BMC_H__ -#include - -#include "kcs_bmc_client.h" +#include #define KCS_BMC_EVENT_NONE 0 #define KCS_BMC_EVENT_HANDLED 1 @@ -17,53 +15,6 @@ #define KCS_BMC_STR_IBF BIT(1) #define KCS_BMC_STR_CMD_DAT BIT(3) -/* Different phases of the KCS BMC module. - * KCS_PHASE_IDLE: - * BMC should not be expecting nor sending any data. - * KCS_PHASE_WRITE_START: - * BMC is receiving a WRITE_START command from system software. - * KCS_PHASE_WRITE_DATA: - * BMC is receiving a data byte from system software. - * KCS_PHASE_WRITE_END_CMD: - * BMC is waiting a last data byte from system software. - * KCS_PHASE_WRITE_DONE: - * BMC has received the whole request from system software. - * KCS_PHASE_WAIT_READ: - * BMC is waiting the response from the upper IPMI service. - * KCS_PHASE_READ: - * BMC is transferring the response to system software. - * KCS_PHASE_ABORT_ERROR1: - * BMC is waiting error status request from system software. - * KCS_PHASE_ABORT_ERROR2: - * BMC is waiting for idle status afer error from system software. - * KCS_PHASE_ERROR: - * BMC has detected a protocol violation at the interface level. - */ -enum kcs_phases { - KCS_PHASE_IDLE, - - KCS_PHASE_WRITE_START, - KCS_PHASE_WRITE_DATA, - KCS_PHASE_WRITE_END_CMD, - KCS_PHASE_WRITE_DONE, - - KCS_PHASE_WAIT_READ, - KCS_PHASE_READ, - - KCS_PHASE_ABORT_ERROR1, - KCS_PHASE_ABORT_ERROR2, - KCS_PHASE_ERROR -}; - -/* IPMI 2.0 - Table 9-4, KCS Interface Status Codes */ -enum kcs_errors { - KCS_NO_ERROR = 0x00, - KCS_ABORTED_BY_COMMAND = 0x01, - KCS_ILLEGAL_CONTROL_CODE = 0x02, - KCS_LENGTH_ERROR = 0x06, - KCS_UNSPECIFIED_ERROR = 0xFF -}; - /* IPMI 2.0 - 9.5, KCS Interface Registers * @idr: Input Data Register * @odr: Output Data Register @@ -76,36 +27,23 @@ struct kcs_ioreg { }; struct kcs_bmc_device_ops; +struct kcs_bmc_client; + +struct kcs_bmc_device { + struct list_head entry; -struct kcs_bmc { struct device *dev; - - const struct kcs_bmc_device_ops *ops; - - struct kcs_bmc_client client; - - spinlock_t lock; - u32 channel; - int running; struct kcs_ioreg ioreg; - enum kcs_phases phase; - enum kcs_errors error; + const struct kcs_bmc_device_ops *ops; - wait_queue_head_t queue; - bool data_in_avail; - int data_in_idx; - u8 *data_in; - - int data_out_idx; - int data_out_len; - u8 *data_out; - - struct mutex mutex; - u8 *kbuffer; - - struct miscdevice miscdev; + spinlock_t lock; + struct kcs_bmc_client *client; }; + +/* Temporary exports while refactoring */ +int kcs_bmc_ipmi_attach_cdev(struct kcs_bmc_device *kcs_bmc); +int kcs_bmc_ipmi_detach_cdev(struct kcs_bmc_device *kcs_bmc); #endif /* __KCS_BMC_H__ */ diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 1b313355b1c8..6f26e7366c0b 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -61,7 +61,7 @@ #define LPC_STR4 0x11C struct aspeed_kcs_bmc { - struct kcs_bmc kcs_bmc; + struct kcs_bmc_device kcs_bmc; struct regmap *map; }; @@ -71,12 +71,12 @@ struct aspeed_kcs_of_ops { int (*get_io_address)(struct platform_device *pdev); }; -static inline struct aspeed_kcs_bmc *to_aspeed_kcs_bmc(struct kcs_bmc *kcs_bmc) +static inline struct aspeed_kcs_bmc *to_aspeed_kcs_bmc(struct kcs_bmc_device *kcs_bmc) { return container_of(kcs_bmc, struct aspeed_kcs_bmc, kcs_bmc); } -static u8 aspeed_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) +static u8 aspeed_kcs_inb(struct kcs_bmc_device *kcs_bmc, u32 reg) { struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); u32 val = 0; @@ -88,7 +88,7 @@ static u8 aspeed_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) return rc == 0 ? (u8) val : 0; } -static void aspeed_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) +static void aspeed_kcs_outb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 data) { struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); int rc; @@ -97,7 +97,7 @@ static void aspeed_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) WARN(rc != 0, "regmap_write() failed: %d\n", rc); } -static void aspeed_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val) +static void aspeed_kcs_updateb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 mask, u8 val) { struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); int rc; @@ -119,7 +119,7 @@ static void aspeed_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 val * C. KCS4 * D / C : CA4h / CA5h */ -static void aspeed_kcs_set_address(struct kcs_bmc *kcs_bmc, u16 addr) +static void aspeed_kcs_set_address(struct kcs_bmc_device *kcs_bmc, u16 addr) { struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); @@ -153,7 +153,7 @@ static void aspeed_kcs_set_address(struct kcs_bmc *kcs_bmc, u16 addr) } } -static void aspeed_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable) +static void aspeed_kcs_enable_channel(struct kcs_bmc_device *kcs_bmc, bool enable) { struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); @@ -228,7 +228,7 @@ static const struct kcs_bmc_device_ops aspeed_kcs_ops = { static irqreturn_t aspeed_kcs_irq(int irq, void *arg) { - struct kcs_bmc *kcs_bmc = arg; + struct kcs_bmc_device *kcs_bmc = arg; int rc; rc = kcs_bmc_handle_event(kcs_bmc); @@ -238,7 +238,7 @@ static irqreturn_t aspeed_kcs_irq(int irq, void *arg) return rc == KCS_BMC_EVENT_HANDLED ? IRQ_HANDLED : IRQ_NONE; } -static int aspeed_kcs_config_irq(struct kcs_bmc *kcs_bmc, +static int aspeed_kcs_config_irq(struct kcs_bmc_device *kcs_bmc, struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -338,8 +338,8 @@ static int aspeed_kcs_of_v2_get_io_address(struct platform_device *pdev) static int aspeed_kcs_probe(struct platform_device *pdev) { const struct aspeed_kcs_of_ops *ops; + struct kcs_bmc_device *kcs_bmc; struct aspeed_kcs_bmc *priv; - struct kcs_bmc *kcs_bmc; struct device_node *np; int rc, channel, addr; @@ -400,7 +400,7 @@ static int aspeed_kcs_probe(struct platform_device *pdev) static int aspeed_kcs_remove(struct platform_device *pdev) { struct aspeed_kcs_bmc *priv = platform_get_drvdata(pdev); - struct kcs_bmc *kcs_bmc = &priv->kcs_bmc; + struct kcs_bmc_device *kcs_bmc = &priv->kcs_bmc; kcs_bmc_remove_device(kcs_bmc); diff --git a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c index fd852d8abe48..58c42e76483d 100644 --- a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c +++ b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c @@ -8,13 +8,88 @@ #include #include #include +#include +#include #include +#include #include #include #include #include -#include "kcs_bmc.h" +#include "kcs_bmc_client.h" + +/* Different phases of the KCS BMC module. + * KCS_PHASE_IDLE: + * BMC should not be expecting nor sending any data. + * KCS_PHASE_WRITE_START: + * BMC is receiving a WRITE_START command from system software. + * KCS_PHASE_WRITE_DATA: + * BMC is receiving a data byte from system software. + * KCS_PHASE_WRITE_END_CMD: + * BMC is waiting a last data byte from system software. + * KCS_PHASE_WRITE_DONE: + * BMC has received the whole request from system software. + * KCS_PHASE_WAIT_READ: + * BMC is waiting the response from the upper IPMI service. + * KCS_PHASE_READ: + * BMC is transferring the response to system software. + * KCS_PHASE_ABORT_ERROR1: + * BMC is waiting error status request from system software. + * KCS_PHASE_ABORT_ERROR2: + * BMC is waiting for idle status afer error from system software. + * KCS_PHASE_ERROR: + * BMC has detected a protocol violation at the interface level. + */ +enum kcs_ipmi_phases { + KCS_PHASE_IDLE, + + KCS_PHASE_WRITE_START, + KCS_PHASE_WRITE_DATA, + KCS_PHASE_WRITE_END_CMD, + KCS_PHASE_WRITE_DONE, + + KCS_PHASE_WAIT_READ, + KCS_PHASE_READ, + + KCS_PHASE_ABORT_ERROR1, + KCS_PHASE_ABORT_ERROR2, + KCS_PHASE_ERROR +}; + +/* IPMI 2.0 - Table 9-4, KCS Interface Status Codes */ +enum kcs_ipmi_errors { + KCS_NO_ERROR = 0x00, + KCS_ABORTED_BY_COMMAND = 0x01, + KCS_ILLEGAL_CONTROL_CODE = 0x02, + KCS_LENGTH_ERROR = 0x06, + KCS_UNSPECIFIED_ERROR = 0xFF +}; + +struct kcs_bmc_ipmi { + struct list_head entry; + + struct kcs_bmc_client client; + + spinlock_t lock; + + enum kcs_ipmi_phases phase; + enum kcs_ipmi_errors error; + + wait_queue_head_t queue; + bool data_in_avail; + int data_in_idx; + u8 *data_in; + + int data_out_idx; + int data_out_len; + u8 *data_out; + + struct mutex mutex; + u8 *kbuffer; + + struct miscdevice miscdev; +}; #define DEVICE_NAME "ipmi-kcs" @@ -44,171 +119,169 @@ enum kcs_states { #define KCS_CMD_WRITE_END 0x62 #define KCS_CMD_READ_BYTE 0x68 -static inline void set_state(struct kcs_bmc *kcs_bmc, u8 state) +static inline void set_state(struct kcs_bmc_ipmi *priv, u8 state) { - kcs_bmc_update_status(kcs_bmc, KCS_STATUS_STATE_MASK, - KCS_STATUS_STATE(state)); + kcs_bmc_update_status(priv->client.dev, KCS_STATUS_STATE_MASK, KCS_STATUS_STATE(state)); } -static void kcs_bmc_ipmi_force_abort(struct kcs_bmc *kcs_bmc) +static void kcs_bmc_ipmi_force_abort(struct kcs_bmc_ipmi *priv) { - set_state(kcs_bmc, ERROR_STATE); - kcs_bmc_read_data(kcs_bmc); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + set_state(priv, ERROR_STATE); + kcs_bmc_read_data(priv->client.dev); + kcs_bmc_write_data(priv->client.dev, KCS_ZERO_DATA); - kcs_bmc->phase = KCS_PHASE_ERROR; - kcs_bmc->data_in_avail = false; - kcs_bmc->data_in_idx = 0; + priv->phase = KCS_PHASE_ERROR; + priv->data_in_avail = false; + priv->data_in_idx = 0; } -static void kcs_bmc_ipmi_handle_data(struct kcs_bmc *kcs_bmc) +static void kcs_bmc_ipmi_handle_data(struct kcs_bmc_ipmi *priv) { + struct kcs_bmc_device *dev; u8 data; - switch (kcs_bmc->phase) { + dev = priv->client.dev; + + switch (priv->phase) { case KCS_PHASE_WRITE_START: - kcs_bmc->phase = KCS_PHASE_WRITE_DATA; + priv->phase = KCS_PHASE_WRITE_DATA; fallthrough; case KCS_PHASE_WRITE_DATA: - if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { - set_state(kcs_bmc, WRITE_STATE); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - kcs_bmc->data_in[kcs_bmc->data_in_idx++] = - kcs_bmc_read_data(kcs_bmc); + if (priv->data_in_idx < KCS_MSG_BUFSIZ) { + set_state(priv, WRITE_STATE); + kcs_bmc_write_data(dev, KCS_ZERO_DATA); + priv->data_in[priv->data_in_idx++] = kcs_bmc_read_data(dev); } else { - kcs_bmc_ipmi_force_abort(kcs_bmc); - kcs_bmc->error = KCS_LENGTH_ERROR; + kcs_bmc_ipmi_force_abort(priv); + priv->error = KCS_LENGTH_ERROR; } break; case KCS_PHASE_WRITE_END_CMD: - if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { - set_state(kcs_bmc, READ_STATE); - kcs_bmc->data_in[kcs_bmc->data_in_idx++] = - kcs_bmc_read_data(kcs_bmc); - kcs_bmc->phase = KCS_PHASE_WRITE_DONE; - kcs_bmc->data_in_avail = true; - wake_up_interruptible(&kcs_bmc->queue); + if (priv->data_in_idx < KCS_MSG_BUFSIZ) { + set_state(priv, READ_STATE); + priv->data_in[priv->data_in_idx++] = kcs_bmc_read_data(dev); + priv->phase = KCS_PHASE_WRITE_DONE; + priv->data_in_avail = true; + wake_up_interruptible(&priv->queue); } else { - kcs_bmc_ipmi_force_abort(kcs_bmc); - kcs_bmc->error = KCS_LENGTH_ERROR; + kcs_bmc_ipmi_force_abort(priv); + priv->error = KCS_LENGTH_ERROR; } break; case KCS_PHASE_READ: - if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) - set_state(kcs_bmc, IDLE_STATE); + if (priv->data_out_idx == priv->data_out_len) + set_state(priv, IDLE_STATE); - data = kcs_bmc_read_data(kcs_bmc); + data = kcs_bmc_read_data(dev); if (data != KCS_CMD_READ_BYTE) { - set_state(kcs_bmc, ERROR_STATE); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + set_state(priv, ERROR_STATE); + kcs_bmc_write_data(dev, KCS_ZERO_DATA); break; } - if (kcs_bmc->data_out_idx == kcs_bmc->data_out_len) { - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - kcs_bmc->phase = KCS_PHASE_IDLE; + if (priv->data_out_idx == priv->data_out_len) { + kcs_bmc_write_data(dev, KCS_ZERO_DATA); + priv->phase = KCS_PHASE_IDLE; break; } - kcs_bmc_write_data(kcs_bmc, - kcs_bmc->data_out[kcs_bmc->data_out_idx++]); + kcs_bmc_write_data(dev, priv->data_out[priv->data_out_idx++]); break; case KCS_PHASE_ABORT_ERROR1: - set_state(kcs_bmc, READ_STATE); - kcs_bmc_read_data(kcs_bmc); - kcs_bmc_write_data(kcs_bmc, kcs_bmc->error); - kcs_bmc->phase = KCS_PHASE_ABORT_ERROR2; + set_state(priv, READ_STATE); + kcs_bmc_read_data(dev); + kcs_bmc_write_data(dev, priv->error); + priv->phase = KCS_PHASE_ABORT_ERROR2; break; case KCS_PHASE_ABORT_ERROR2: - set_state(kcs_bmc, IDLE_STATE); - kcs_bmc_read_data(kcs_bmc); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); - kcs_bmc->phase = KCS_PHASE_IDLE; + set_state(priv, IDLE_STATE); + kcs_bmc_read_data(dev); + kcs_bmc_write_data(dev, KCS_ZERO_DATA); + priv->phase = KCS_PHASE_IDLE; break; default: - kcs_bmc_ipmi_force_abort(kcs_bmc); + kcs_bmc_ipmi_force_abort(priv); break; } } -static void kcs_bmc_ipmi_handle_cmd(struct kcs_bmc *kcs_bmc) +static void kcs_bmc_ipmi_handle_cmd(struct kcs_bmc_ipmi *priv) { u8 cmd; - set_state(kcs_bmc, WRITE_STATE); - kcs_bmc_write_data(kcs_bmc, KCS_ZERO_DATA); + set_state(priv, WRITE_STATE); + kcs_bmc_write_data(priv->client.dev, KCS_ZERO_DATA); - cmd = kcs_bmc_read_data(kcs_bmc); + cmd = kcs_bmc_read_data(priv->client.dev); switch (cmd) { case KCS_CMD_WRITE_START: - kcs_bmc->phase = KCS_PHASE_WRITE_START; - kcs_bmc->error = KCS_NO_ERROR; - kcs_bmc->data_in_avail = false; - kcs_bmc->data_in_idx = 0; + priv->phase = KCS_PHASE_WRITE_START; + priv->error = KCS_NO_ERROR; + priv->data_in_avail = false; + priv->data_in_idx = 0; break; case KCS_CMD_WRITE_END: - if (kcs_bmc->phase != KCS_PHASE_WRITE_DATA) { - kcs_bmc_ipmi_force_abort(kcs_bmc); + if (priv->phase != KCS_PHASE_WRITE_DATA) { + kcs_bmc_ipmi_force_abort(priv); break; } - kcs_bmc->phase = KCS_PHASE_WRITE_END_CMD; + priv->phase = KCS_PHASE_WRITE_END_CMD; break; case KCS_CMD_GET_STATUS_ABORT: - if (kcs_bmc->error == KCS_NO_ERROR) - kcs_bmc->error = KCS_ABORTED_BY_COMMAND; + if (priv->error == KCS_NO_ERROR) + priv->error = KCS_ABORTED_BY_COMMAND; - kcs_bmc->phase = KCS_PHASE_ABORT_ERROR1; - kcs_bmc->data_in_avail = false; - kcs_bmc->data_in_idx = 0; + priv->phase = KCS_PHASE_ABORT_ERROR1; + priv->data_in_avail = false; + priv->data_in_idx = 0; break; default: - kcs_bmc_ipmi_force_abort(kcs_bmc); - kcs_bmc->error = KCS_ILLEGAL_CONTROL_CODE; + kcs_bmc_ipmi_force_abort(priv); + priv->error = KCS_ILLEGAL_CONTROL_CODE; break; } } -static inline struct kcs_bmc *client_to_kcs_bmc(struct kcs_bmc_client *client) +static inline struct kcs_bmc_ipmi *client_to_kcs_bmc_ipmi(struct kcs_bmc_client *client) { - return container_of(client, struct kcs_bmc, client); + return container_of(client, struct kcs_bmc_ipmi, client); } static int kcs_bmc_ipmi_event(struct kcs_bmc_client *client) { - struct kcs_bmc *kcs_bmc; - unsigned long flags; + struct kcs_bmc_ipmi *priv; u8 status; int ret; - kcs_bmc = client_to_kcs_bmc(client); + priv = client_to_kcs_bmc_ipmi(client); + if (!priv) + return KCS_BMC_EVENT_NONE; - spin_lock_irqsave(&kcs_bmc->lock, flags); + spin_lock(&priv->lock); - status = kcs_bmc_read_status(kcs_bmc); + status = kcs_bmc_read_status(client->dev); if (status & KCS_STATUS_IBF) { - if (!kcs_bmc->running) - kcs_bmc_ipmi_force_abort(kcs_bmc); - else if (status & KCS_STATUS_CMD_DAT) - kcs_bmc_ipmi_handle_cmd(kcs_bmc); + if (status & KCS_STATUS_CMD_DAT) + kcs_bmc_ipmi_handle_cmd(priv); else - kcs_bmc_ipmi_handle_data(kcs_bmc); + kcs_bmc_ipmi_handle_data(priv); ret = KCS_BMC_EVENT_HANDLED; } else { ret = KCS_BMC_EVENT_NONE; } - spin_unlock_irqrestore(&kcs_bmc->lock, flags); + spin_unlock(&priv->lock); return ret; } @@ -217,37 +290,29 @@ static const struct kcs_bmc_client_ops kcs_bmc_ipmi_client_ops = { .event = kcs_bmc_ipmi_event, }; -static inline struct kcs_bmc *file_to_kcs_bmc(struct file *filp) +static inline struct kcs_bmc_ipmi *to_kcs_bmc(struct file *filp) { - return container_of(filp->private_data, struct kcs_bmc, miscdev); + return container_of(filp->private_data, struct kcs_bmc_ipmi, miscdev); } static int kcs_bmc_ipmi_open(struct inode *inode, struct file *filp) { - struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); - int ret = 0; + struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp); - spin_lock_irq(&kcs_bmc->lock); - if (!kcs_bmc->running) - kcs_bmc->running = 1; - else - ret = -EBUSY; - spin_unlock_irq(&kcs_bmc->lock); - - return ret; + return kcs_bmc_enable_device(priv->client.dev, &priv->client); } static __poll_t kcs_bmc_ipmi_poll(struct file *filp, poll_table *wait) { - struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); + struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp); __poll_t mask = 0; - poll_wait(filp, &kcs_bmc->queue, wait); + poll_wait(filp, &priv->queue, wait); - spin_lock_irq(&kcs_bmc->lock); - if (kcs_bmc->data_in_avail) + spin_lock_irq(&priv->lock); + if (priv->data_in_avail) mask |= EPOLLIN; - spin_unlock_irq(&kcs_bmc->lock); + spin_unlock_irq(&priv->lock); return mask; } @@ -255,24 +320,24 @@ static __poll_t kcs_bmc_ipmi_poll(struct file *filp, poll_table *wait) static ssize_t kcs_bmc_ipmi_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { - struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); + struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp); bool data_avail; size_t data_len; ssize_t ret; if (!(filp->f_flags & O_NONBLOCK)) - wait_event_interruptible(kcs_bmc->queue, - kcs_bmc->data_in_avail); + wait_event_interruptible(priv->queue, + priv->data_in_avail); - mutex_lock(&kcs_bmc->mutex); + mutex_lock(&priv->mutex); - spin_lock_irq(&kcs_bmc->lock); - data_avail = kcs_bmc->data_in_avail; + spin_lock_irq(&priv->lock); + data_avail = priv->data_in_avail; if (data_avail) { - data_len = kcs_bmc->data_in_idx; - memcpy(kcs_bmc->kbuffer, kcs_bmc->data_in, data_len); + data_len = priv->data_in_idx; + memcpy(priv->kbuffer, priv->data_in, data_len); } - spin_unlock_irq(&kcs_bmc->lock); + spin_unlock_irq(&priv->lock); if (!data_avail) { ret = -EAGAIN; @@ -281,35 +346,35 @@ static ssize_t kcs_bmc_ipmi_read(struct file *filp, char __user *buf, if (count < data_len) { pr_err("channel=%u with too large data : %zu\n", - kcs_bmc->channel, data_len); + priv->client.dev->channel, data_len); - spin_lock_irq(&kcs_bmc->lock); - kcs_bmc_ipmi_force_abort(kcs_bmc); - spin_unlock_irq(&kcs_bmc->lock); + spin_lock_irq(&priv->lock); + kcs_bmc_ipmi_force_abort(priv); + spin_unlock_irq(&priv->lock); ret = -EOVERFLOW; goto out_unlock; } - if (copy_to_user(buf, kcs_bmc->kbuffer, data_len)) { + if (copy_to_user(buf, priv->kbuffer, data_len)) { ret = -EFAULT; goto out_unlock; } ret = data_len; - spin_lock_irq(&kcs_bmc->lock); - if (kcs_bmc->phase == KCS_PHASE_WRITE_DONE) { - kcs_bmc->phase = KCS_PHASE_WAIT_READ; - kcs_bmc->data_in_avail = false; - kcs_bmc->data_in_idx = 0; + spin_lock_irq(&priv->lock); + if (priv->phase == KCS_PHASE_WRITE_DONE) { + priv->phase = KCS_PHASE_WAIT_READ; + priv->data_in_avail = false; + priv->data_in_idx = 0; } else { ret = -EAGAIN; } - spin_unlock_irq(&kcs_bmc->lock); + spin_unlock_irq(&priv->lock); out_unlock: - mutex_unlock(&kcs_bmc->mutex); + mutex_unlock(&priv->mutex); return ret; } @@ -317,35 +382,35 @@ static ssize_t kcs_bmc_ipmi_read(struct file *filp, char __user *buf, static ssize_t kcs_bmc_ipmi_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { - struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); + struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp); ssize_t ret; /* a minimum response size '3' : netfn + cmd + ccode */ if (count < 3 || count > KCS_MSG_BUFSIZ) return -EINVAL; - mutex_lock(&kcs_bmc->mutex); + mutex_lock(&priv->mutex); - if (copy_from_user(kcs_bmc->kbuffer, buf, count)) { + if (copy_from_user(priv->kbuffer, buf, count)) { ret = -EFAULT; goto out_unlock; } - spin_lock_irq(&kcs_bmc->lock); - if (kcs_bmc->phase == KCS_PHASE_WAIT_READ) { - kcs_bmc->phase = KCS_PHASE_READ; - kcs_bmc->data_out_idx = 1; - kcs_bmc->data_out_len = count; - memcpy(kcs_bmc->data_out, kcs_bmc->kbuffer, count); - kcs_bmc_write_data(kcs_bmc, kcs_bmc->data_out[0]); + spin_lock_irq(&priv->lock); + if (priv->phase == KCS_PHASE_WAIT_READ) { + priv->phase = KCS_PHASE_READ; + priv->data_out_idx = 1; + priv->data_out_len = count; + memcpy(priv->data_out, priv->kbuffer, count); + kcs_bmc_write_data(priv->client.dev, priv->data_out[0]); ret = count; } else { ret = -EINVAL; } - spin_unlock_irq(&kcs_bmc->lock); + spin_unlock_irq(&priv->lock); out_unlock: - mutex_unlock(&kcs_bmc->mutex); + mutex_unlock(&priv->mutex); return ret; } @@ -353,22 +418,22 @@ static ssize_t kcs_bmc_ipmi_write(struct file *filp, const char __user *buf, static long kcs_bmc_ipmi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); + struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp); long ret = 0; - spin_lock_irq(&kcs_bmc->lock); + spin_lock_irq(&priv->lock); switch (cmd) { case IPMI_BMC_IOCTL_SET_SMS_ATN: - kcs_bmc_update_status(kcs_bmc, KCS_STATUS_SMS_ATN, KCS_STATUS_SMS_ATN); + kcs_bmc_update_status(priv->client.dev, KCS_STATUS_SMS_ATN, KCS_STATUS_SMS_ATN); break; case IPMI_BMC_IOCTL_CLEAR_SMS_ATN: - kcs_bmc_update_status(kcs_bmc, KCS_STATUS_SMS_ATN, 0); + kcs_bmc_update_status(priv->client.dev, KCS_STATUS_SMS_ATN, 0); break; case IPMI_BMC_IOCTL_FORCE_ABORT: - kcs_bmc_ipmi_force_abort(kcs_bmc); + kcs_bmc_ipmi_force_abort(priv); break; default: @@ -376,19 +441,17 @@ static long kcs_bmc_ipmi_ioctl(struct file *filp, unsigned int cmd, break; } - spin_unlock_irq(&kcs_bmc->lock); + spin_unlock_irq(&priv->lock); return ret; } static int kcs_bmc_ipmi_release(struct inode *inode, struct file *filp) { - struct kcs_bmc *kcs_bmc = file_to_kcs_bmc(filp); + struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp); - spin_lock_irq(&kcs_bmc->lock); - kcs_bmc->running = 0; - kcs_bmc_ipmi_force_abort(kcs_bmc); - spin_unlock_irq(&kcs_bmc->lock); + kcs_bmc_ipmi_force_abort(priv); + kcs_bmc_disable_device(priv->client.dev, &priv->client); return 0; } @@ -403,56 +466,78 @@ static const struct file_operations kcs_bmc_ipmi_fops = { .unlocked_ioctl = kcs_bmc_ipmi_ioctl, }; -int kcs_bmc_ipmi_attach_cdev(struct kcs_bmc *kcs_bmc); -int kcs_bmc_ipmi_attach_cdev(struct kcs_bmc *kcs_bmc) +static DEFINE_SPINLOCK(kcs_bmc_ipmi_instances_lock); +static LIST_HEAD(kcs_bmc_ipmi_instances); + +int kcs_bmc_ipmi_attach_cdev(struct kcs_bmc_device *kcs_bmc); +int kcs_bmc_ipmi_attach_cdev(struct kcs_bmc_device *kcs_bmc) { + struct kcs_bmc_ipmi *priv; int rc; - spin_lock_init(&kcs_bmc->lock); - mutex_init(&kcs_bmc->mutex); - init_waitqueue_head(&kcs_bmc->queue); - - kcs_bmc->client.dev = kcs_bmc; - kcs_bmc->client.ops = &kcs_bmc_ipmi_client_ops; - kcs_bmc->data_in = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); - kcs_bmc->data_out = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); - kcs_bmc->kbuffer = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); - - kcs_bmc->miscdev.minor = MISC_DYNAMIC_MINOR; - kcs_bmc->miscdev.name = devm_kasprintf(kcs_bmc->dev, GFP_KERNEL, "%s%u", - DEVICE_NAME, kcs_bmc->channel); - if (!kcs_bmc->data_in || !kcs_bmc->data_out || !kcs_bmc->kbuffer || - !kcs_bmc->miscdev.name) + priv = devm_kzalloc(kcs_bmc->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) return -ENOMEM; - kcs_bmc->miscdev.fops = &kcs_bmc_ipmi_fops; + spin_lock_init(&priv->lock); + mutex_init(&priv->mutex); - rc = misc_register(&kcs_bmc->miscdev); + init_waitqueue_head(&priv->queue); + + priv->client.dev = kcs_bmc; + priv->client.ops = &kcs_bmc_ipmi_client_ops; + priv->data_in = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + priv->data_out = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + priv->kbuffer = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL); + + priv->miscdev.minor = MISC_DYNAMIC_MINOR; + priv->miscdev.name = devm_kasprintf(kcs_bmc->dev, GFP_KERNEL, "%s%u", DEVICE_NAME, + kcs_bmc->channel); + if (!priv->data_in || !priv->data_out || !priv->kbuffer || !priv->miscdev.name) + return -EINVAL; + + priv->miscdev.fops = &kcs_bmc_ipmi_fops; + + rc = misc_register(&priv->miscdev); if (rc) { dev_err(kcs_bmc->dev, "Unable to register device: %d\n", rc); return rc; } + spin_lock_irq(&kcs_bmc_ipmi_instances_lock); + list_add(&priv->entry, &kcs_bmc_ipmi_instances); + spin_unlock_irq(&kcs_bmc_ipmi_instances_lock); + dev_info(kcs_bmc->dev, "Initialised IPMI client for channel %d", kcs_bmc->channel); return 0; } EXPORT_SYMBOL(kcs_bmc_ipmi_attach_cdev); -int kcs_bmc_ipmi_detach_cdev(struct kcs_bmc *kcs_bmc); -int kcs_bmc_ipmi_detach_cdev(struct kcs_bmc *kcs_bmc) +int kcs_bmc_ipmi_detach_cdev(struct kcs_bmc_device *kcs_bmc); +int kcs_bmc_ipmi_detach_cdev(struct kcs_bmc_device *kcs_bmc) { - misc_deregister(&kcs_bmc->miscdev); + struct kcs_bmc_ipmi *priv = NULL, *pos; - spin_lock_irq(&kcs_bmc->lock); - kcs_bmc->running = 0; - kcs_bmc_ipmi_force_abort(kcs_bmc); - spin_unlock_irq(&kcs_bmc->lock); + spin_lock_irq(&kcs_bmc_ipmi_instances_lock); + list_for_each_entry(pos, &kcs_bmc_ipmi_instances, entry) { + if (pos->client.dev == kcs_bmc) { + priv = pos; + list_del(&pos->entry); + break; + } + } + spin_unlock_irq(&kcs_bmc_ipmi_instances_lock); - devm_kfree(kcs_bmc->dev, kcs_bmc->kbuffer); - devm_kfree(kcs_bmc->dev, kcs_bmc->data_out); - devm_kfree(kcs_bmc->dev, kcs_bmc->data_in); - devm_kfree(kcs_bmc->dev, kcs_bmc); + if (!priv) + return 0; + + misc_deregister(&priv->miscdev); + kcs_bmc_disable_device(priv->client.dev, &priv->client); + devm_kfree(kcs_bmc->dev, priv->kbuffer); + devm_kfree(kcs_bmc->dev, priv->data_out); + devm_kfree(kcs_bmc->dev, priv->data_in); + devm_kfree(kcs_bmc->dev, priv); return 0; } @@ -460,4 +545,5 @@ EXPORT_SYMBOL(kcs_bmc_ipmi_detach_cdev); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Haiyue Wang "); +MODULE_AUTHOR("Andrew Jeffery "); MODULE_DESCRIPTION("KCS BMC to handle the IPMI request from system software"); diff --git a/drivers/char/ipmi/kcs_bmc_client.h b/drivers/char/ipmi/kcs_bmc_client.h index 140631d157d8..2dd710f4b4aa 100644 --- a/drivers/char/ipmi/kcs_bmc_client.h +++ b/drivers/char/ipmi/kcs_bmc_client.h @@ -8,22 +8,24 @@ #include #include -struct kcs_bmc; -struct kcs_bmc_client_ops; - -struct kcs_bmc_client { - const struct kcs_bmc_client_ops *ops; - - struct kcs_bmc *dev; -}; +#include "kcs_bmc.h" struct kcs_bmc_client_ops { int (*event)(struct kcs_bmc_client *client); }; -u8 kcs_bmc_read_data(struct kcs_bmc *kcs_bmc); -void kcs_bmc_write_data(struct kcs_bmc *kcs_bmc, u8 data); -u8 kcs_bmc_read_status(struct kcs_bmc *kcs_bmc); -void kcs_bmc_write_status(struct kcs_bmc *kcs_bmc, u8 data); -void kcs_bmc_update_status(struct kcs_bmc *kcs_bmc, u8 mask, u8 val); +struct kcs_bmc_client { + const struct kcs_bmc_client_ops *ops; + + struct kcs_bmc_device *dev; +}; + +int kcs_bmc_enable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client); +void kcs_bmc_disable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client); + +u8 kcs_bmc_read_data(struct kcs_bmc_device *kcs_bmc); +void kcs_bmc_write_data(struct kcs_bmc_device *kcs_bmc, u8 data); +u8 kcs_bmc_read_status(struct kcs_bmc_device *kcs_bmc); +void kcs_bmc_write_status(struct kcs_bmc_device *kcs_bmc, u8 data); +void kcs_bmc_update_status(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 val); #endif diff --git a/drivers/char/ipmi/kcs_bmc_device.h b/drivers/char/ipmi/kcs_bmc_device.h index 33462174516d..57b7174b2bac 100644 --- a/drivers/char/ipmi/kcs_bmc_device.h +++ b/drivers/char/ipmi/kcs_bmc_device.h @@ -7,13 +7,13 @@ #include "kcs_bmc.h" struct kcs_bmc_device_ops { - u8 (*io_inputb)(struct kcs_bmc *kcs_bmc, u32 reg); - void (*io_outputb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 b); - void (*io_updateb)(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 b); + u8 (*io_inputb)(struct kcs_bmc_device *kcs_bmc, u32 reg); + void (*io_outputb)(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 b); + void (*io_updateb)(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 mask, u8 b); }; -int kcs_bmc_handle_event(struct kcs_bmc *kcs_bmc); -int kcs_bmc_add_device(struct kcs_bmc *kcs_bmc); -int kcs_bmc_remove_device(struct kcs_bmc *kcs_bmc); +int kcs_bmc_handle_event(struct kcs_bmc_device *kcs_bmc); +int kcs_bmc_add_device(struct kcs_bmc_device *kcs_bmc); +int kcs_bmc_remove_device(struct kcs_bmc_device *kcs_bmc); #endif diff --git a/drivers/char/ipmi/kcs_bmc_npcm7xx.c b/drivers/char/ipmi/kcs_bmc_npcm7xx.c index 1d21697fc585..dce93ec895fc 100644 --- a/drivers/char/ipmi/kcs_bmc_npcm7xx.c +++ b/drivers/char/ipmi/kcs_bmc_npcm7xx.c @@ -65,7 +65,7 @@ struct npcm7xx_kcs_reg { }; struct npcm7xx_kcs_bmc { - struct kcs_bmc kcs_bmc; + struct kcs_bmc_device kcs_bmc; struct regmap *map; @@ -78,12 +78,12 @@ static const struct npcm7xx_kcs_reg npcm7xx_kcs_reg_tbl[KCS_CHANNEL_MAX] = { { .sts = KCS3ST, .dob = KCS3DO, .dib = KCS3DI, .ctl = KCS3CTL, .ie = KCS3IE }, }; -static inline struct npcm7xx_kcs_bmc *to_npcm7xx_kcs_bmc(struct kcs_bmc *kcs_bmc) +static inline struct npcm7xx_kcs_bmc *to_npcm7xx_kcs_bmc(struct kcs_bmc_device *kcs_bmc) { return container_of(kcs_bmc, struct npcm7xx_kcs_bmc, kcs_bmc); } -static u8 npcm7xx_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) +static u8 npcm7xx_kcs_inb(struct kcs_bmc_device *kcs_bmc, u32 reg) { struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); u32 val = 0; @@ -95,7 +95,7 @@ static u8 npcm7xx_kcs_inb(struct kcs_bmc *kcs_bmc, u32 reg) return rc == 0 ? (u8)val : 0; } -static void npcm7xx_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) +static void npcm7xx_kcs_outb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 data) { struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); int rc; @@ -104,7 +104,7 @@ static void npcm7xx_kcs_outb(struct kcs_bmc *kcs_bmc, u32 reg, u8 data) WARN(rc != 0, "regmap_write() failed: %d\n", rc); } -static void npcm7xx_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 data) +static void npcm7xx_kcs_updateb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 mask, u8 data) { struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); int rc; @@ -113,7 +113,7 @@ static void npcm7xx_kcs_updateb(struct kcs_bmc *kcs_bmc, u32 reg, u8 mask, u8 da WARN(rc != 0, "regmap_update_bits() failed: %d\n", rc); } -static void npcm7xx_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable) +static void npcm7xx_kcs_enable_channel(struct kcs_bmc_device *kcs_bmc, bool enable) { struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); @@ -126,7 +126,7 @@ static void npcm7xx_kcs_enable_channel(struct kcs_bmc *kcs_bmc, bool enable) static irqreturn_t npcm7xx_kcs_irq(int irq, void *arg) { - struct kcs_bmc *kcs_bmc = arg; + struct kcs_bmc_device *kcs_bmc = arg; int rc; rc = kcs_bmc_handle_event(kcs_bmc); @@ -136,7 +136,7 @@ static irqreturn_t npcm7xx_kcs_irq(int irq, void *arg) return rc == KCS_BMC_EVENT_HANDLED ? IRQ_HANDLED : IRQ_NONE; } -static int npcm7xx_kcs_config_irq(struct kcs_bmc *kcs_bmc, +static int npcm7xx_kcs_config_irq(struct kcs_bmc_device *kcs_bmc, struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -160,7 +160,7 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct npcm7xx_kcs_bmc *priv; - struct kcs_bmc *kcs_bmc; + struct kcs_bmc_device *kcs_bmc; u32 chan; int rc; @@ -207,7 +207,7 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) static int npcm7xx_kcs_remove(struct platform_device *pdev) { struct npcm7xx_kcs_bmc *priv = platform_get_drvdata(pdev); - struct kcs_bmc *kcs_bmc = &priv->kcs_bmc; + struct kcs_bmc_device *kcs_bmc = &priv->kcs_bmc; kcs_bmc_remove_device(kcs_bmc); From patchwork Fri Mar 19 06:27:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455605 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=Nx7n3I54; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=HqA+Y5rX; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vCN2jCrz9sWF for ; Fri, 19 Mar 2021 17:30:24 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234047AbhCSG3q (ORCPT ); Fri, 19 Mar 2021 02:29:46 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:40173 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234018AbhCSG3h (ORCPT ); Fri, 19 Mar 2021 02:29:37 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id DE852580A7B; Fri, 19 Mar 2021 02:29:36 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:29:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=Q2miSwLqRNV3E hwMpXHGmYjjEg834SrPc8bx9cmDie8=; b=Nx7n3I541OknayZgEWBA9zlpY2CNK MOVgrMd9t3n/yAZcHpvTjNPaotr8CfpEGBwwz5tLp3bGPh0+89RklTkuRRFfx4Uw K+hdoGrTxsw1gmXduVQetLcMvR26WW8khqjk+ppL7QeeNDOjSbzKhP+ZvKB1W87i gPUuagiA3mOdfyfQKmg6/HL0o0HndcdbXcNM4kDx7gmb7RdaLmx3bupl+kpmo3HU PlHJb5YR9rtVanJYMiK9SoWDH28tkljuGHiJMVeaZhm2viIggGmAAo6AXjGBn71c MSGIcoWLPQsUcYN5DjZXgxdX/+CLq5CXAI7Cz14zY7TJD902uM5y6cl/g== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=Q2miSwLqRNV3EhwMpXHGmYjjEg834SrPc8bx9cmDie8=; b=HqA+Y5rX eBgOQigjRY+pciDxyDeP4WX9DetiOz/idnStJKGY60Hj+UwFV51pH7q6DDNzstL1 igm+rrrCvW010X2dgEG85Gz8NDPf11GkLScA+gx+7kbok4uTNQ8K2tzJkYlfzKEh Isng+GAo6E9B4vq0Ur5S5CNLZ0ltjjHlAYOz4sBITS4Ujl6xO4lNA/x0eIMRtOOf 2F01UrMnICv1buIKYU5UG2X2MfuCkii/KH04dUm1vahosFMxHFvP605XZ4XxaCc0 TxHNOxjRyKTCfq5A5jkdzyeN+0kTI4wIzoajpjjvMPn6XiGDVdFNQG0rqjmthXbs iXLL6w+R1/1kPA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppeduudekrddvuddtrddukedurdeh heenucevlhhushhtvghrufhiiigvpeegnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnh gurhgvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 4F437240057; Fri, 19 Mar 2021 02:29:31 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, chiawei_wang@aspeedtech.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 13/21] ipmi: kcs_bmc: Decouple the IPMI chardev from the core Date: Fri, 19 Mar 2021 16:57:44 +1030 Message-Id: <20210319062752.145730-13-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Now that we have untangled the data-structures, split the userspace interface out into its own module. Userspace interfaces and drivers are registered to the KCS BMC core to support arbitrary binding of either. Signed-off-by: Andrew Jeffery Tested-by: Chia-Wei Wang --- drivers/char/ipmi/Kconfig | 13 +++++ drivers/char/ipmi/Makefile | 3 +- drivers/char/ipmi/kcs_bmc.c | 78 ++++++++++++++++++++++++++- drivers/char/ipmi/kcs_bmc.h | 4 -- drivers/char/ipmi/kcs_bmc_cdev_ipmi.c | 33 +++++++++--- drivers/char/ipmi/kcs_bmc_client.h | 14 +++++ 6 files changed, 132 insertions(+), 13 deletions(-) diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig index 07847d9a459a..bc5f81899b62 100644 --- a/drivers/char/ipmi/Kconfig +++ b/drivers/char/ipmi/Kconfig @@ -124,6 +124,19 @@ config NPCM7XX_KCS_IPMI_BMC This support is also available as a module. If so, the module will be called kcs_bmc_npcm7xx. +config IPMI_KCS_BMC_CDEV_IPMI + depends on IPMI_KCS_BMC + tristate "IPMI character device interface for BMC KCS devices" + help + Provides a BMC-side character device implementing IPMI + semantics for KCS IPMI devices. + + Say YES if you wish to expose KCS devices on the BMC for IPMI + purposes. + + This support is also available as a module. The module will be + called kcs_bmc_cdev_ipmi. + config ASPEED_BT_IPMI_BMC depends on ARCH_ASPEED || COMPILE_TEST depends on REGMAP && REGMAP_MMIO && MFD_SYSCON diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile index a302bc865370..fcfa676afddb 100644 --- a/drivers/char/ipmi/Makefile +++ b/drivers/char/ipmi/Makefile @@ -22,7 +22,8 @@ obj-$(CONFIG_IPMI_SSIF) += ipmi_ssif.o obj-$(CONFIG_IPMI_POWERNV) += ipmi_powernv.o obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o -obj-$(CONFIG_IPMI_KCS_BMC) += kcs_bmc.o kcs_bmc_cdev_ipmi.o +obj-$(CONFIG_IPMI_KCS_BMC) += kcs_bmc.o +obj-$(CONFIG_IPMI_KCS_BMC_CDEV_IPMI) += kcs_bmc_cdev_ipmi.o obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o obj-$(CONFIG_ASPEED_KCS_IPMI_BMC) += kcs_bmc_aspeed.o obj-$(CONFIG_NPCM7XX_KCS_IPMI_BMC) += kcs_bmc_npcm7xx.o diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index 266ebec71d6f..694db6ee2a92 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -5,7 +5,9 @@ */ #include +#include #include +#include #include "kcs_bmc.h" @@ -13,6 +15,11 @@ #include "kcs_bmc_device.h" #include "kcs_bmc_client.h" +/* Record probed devices and cdevs */ +static DEFINE_MUTEX(kcs_bmc_lock); +static LIST_HEAD(kcs_bmc_devices); +static LIST_HEAD(kcs_bmc_cdevs); + /* Consumer data access */ u8 kcs_bmc_read_data(struct kcs_bmc_device *kcs_bmc) @@ -100,16 +107,83 @@ EXPORT_SYMBOL(kcs_bmc_disable_device); int kcs_bmc_add_device(struct kcs_bmc_device *kcs_bmc) { - return kcs_bmc_ipmi_attach_cdev(kcs_bmc); + struct kcs_bmc_cdev *cdev; + int rc; + + spin_lock_init(&kcs_bmc->lock); + kcs_bmc->client = NULL; + + mutex_lock(&kcs_bmc_lock); + list_add(&kcs_bmc->entry, &kcs_bmc_devices); + list_for_each_entry(cdev, &kcs_bmc_cdevs, entry) { + rc = cdev->ops->add_device(kcs_bmc); + if (rc) + dev_err(kcs_bmc->dev, "Failed to add chardev for KCS channel %d: %d", + kcs_bmc->channel, rc); + } + mutex_unlock(&kcs_bmc_lock); + + return 0; } EXPORT_SYMBOL(kcs_bmc_add_device); int kcs_bmc_remove_device(struct kcs_bmc_device *kcs_bmc) { - return kcs_bmc_ipmi_detach_cdev(kcs_bmc); + struct kcs_bmc_cdev *cdev; + int rc; + + mutex_lock(&kcs_bmc_lock); + list_del(&kcs_bmc->entry); + list_for_each_entry(cdev, &kcs_bmc_cdevs, entry) { + rc = cdev->ops->remove_device(kcs_bmc); + if (rc) + dev_err(kcs_bmc->dev, "Failed to remove chardev for KCS channel %d: %d", + kcs_bmc->channel, rc); + } + mutex_unlock(&kcs_bmc_lock); + + return 0; } EXPORT_SYMBOL(kcs_bmc_remove_device); +int kcs_bmc_register_cdev(struct kcs_bmc_cdev *cdev) +{ + struct kcs_bmc_device *kcs_bmc; + int rc; + + mutex_lock(&kcs_bmc_lock); + list_add(&cdev->entry, &kcs_bmc_cdevs); + list_for_each_entry(kcs_bmc, &kcs_bmc_devices, entry) { + rc = cdev->ops->add_device(kcs_bmc); + if (rc) + dev_err(kcs_bmc->dev, "Failed to add chardev for KCS channel %d: %d", + kcs_bmc->channel, rc); + } + mutex_unlock(&kcs_bmc_lock); + + return 0; +} +EXPORT_SYMBOL(kcs_bmc_register_cdev); + +int kcs_bmc_unregister_cdev(struct kcs_bmc_cdev *cdev) +{ + struct kcs_bmc_device *kcs_bmc; + int rc; + + mutex_lock(&kcs_bmc_lock); + list_del(&cdev->entry); + list_for_each_entry(kcs_bmc, &kcs_bmc_devices, entry) { + rc = cdev->ops->remove_device(kcs_bmc); + if (rc) + dev_err(kcs_bmc->dev, "Failed to add chardev for KCS channel %d: %d", + kcs_bmc->channel, rc); + } + mutex_unlock(&kcs_bmc_lock); + + return rc; +} +EXPORT_SYMBOL(kcs_bmc_unregister_cdev); + MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Haiyue Wang "); MODULE_AUTHOR("Andrew Jeffery "); diff --git a/drivers/char/ipmi/kcs_bmc.h b/drivers/char/ipmi/kcs_bmc.h index 3f266740c759..5deb9a0b8e60 100644 --- a/drivers/char/ipmi/kcs_bmc.h +++ b/drivers/char/ipmi/kcs_bmc.h @@ -42,8 +42,4 @@ struct kcs_bmc_device { spinlock_t lock; struct kcs_bmc_client *client; }; - -/* Temporary exports while refactoring */ -int kcs_bmc_ipmi_attach_cdev(struct kcs_bmc_device *kcs_bmc); -int kcs_bmc_ipmi_detach_cdev(struct kcs_bmc_device *kcs_bmc); #endif /* __KCS_BMC_H__ */ diff --git a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c index 58c42e76483d..df83d67851ac 100644 --- a/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c +++ b/drivers/char/ipmi/kcs_bmc_cdev_ipmi.c @@ -469,8 +469,7 @@ static const struct file_operations kcs_bmc_ipmi_fops = { static DEFINE_SPINLOCK(kcs_bmc_ipmi_instances_lock); static LIST_HEAD(kcs_bmc_ipmi_instances); -int kcs_bmc_ipmi_attach_cdev(struct kcs_bmc_device *kcs_bmc); -int kcs_bmc_ipmi_attach_cdev(struct kcs_bmc_device *kcs_bmc) +static int kcs_bmc_ipmi_attach_cdev(struct kcs_bmc_device *kcs_bmc) { struct kcs_bmc_ipmi *priv; int rc; @@ -512,10 +511,8 @@ int kcs_bmc_ipmi_attach_cdev(struct kcs_bmc_device *kcs_bmc) return 0; } -EXPORT_SYMBOL(kcs_bmc_ipmi_attach_cdev); -int kcs_bmc_ipmi_detach_cdev(struct kcs_bmc_device *kcs_bmc); -int kcs_bmc_ipmi_detach_cdev(struct kcs_bmc_device *kcs_bmc) +static int kcs_bmc_ipmi_detach_cdev(struct kcs_bmc_device *kcs_bmc) { struct kcs_bmc_ipmi *priv = NULL, *pos; @@ -541,7 +538,31 @@ int kcs_bmc_ipmi_detach_cdev(struct kcs_bmc_device *kcs_bmc) return 0; } -EXPORT_SYMBOL(kcs_bmc_ipmi_detach_cdev); + +static const struct kcs_bmc_cdev_ops kcs_bmc_ipmi_cdev_ops = { + .add_device = kcs_bmc_ipmi_attach_cdev, + .remove_device = kcs_bmc_ipmi_detach_cdev, +}; + +static struct kcs_bmc_cdev kcs_bmc_ipmi_cdev = { + .ops = &kcs_bmc_ipmi_cdev_ops, +}; + +static int kcs_bmc_ipmi_init(void) +{ + return kcs_bmc_register_cdev(&kcs_bmc_ipmi_cdev); +} +module_init(kcs_bmc_ipmi_init); + +static void kcs_bmc_ipmi_exit(void) +{ + int rc; + + rc = kcs_bmc_unregister_cdev(&kcs_bmc_ipmi_cdev); + if (rc) + pr_warn("Failed to remove KCS BMC client: %d", rc); +} +module_exit(kcs_bmc_ipmi_exit); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Haiyue Wang "); diff --git a/drivers/char/ipmi/kcs_bmc_client.h b/drivers/char/ipmi/kcs_bmc_client.h index 2dd710f4b4aa..d0a7404ff584 100644 --- a/drivers/char/ipmi/kcs_bmc_client.h +++ b/drivers/char/ipmi/kcs_bmc_client.h @@ -10,6 +10,17 @@ #include "kcs_bmc.h" +struct kcs_bmc_cdev_ops { + int (*add_device)(struct kcs_bmc_device *kcs_bmc); + int (*remove_device)(struct kcs_bmc_device *kcs_bmc); +}; + +struct kcs_bmc_cdev { + struct list_head entry; + + const struct kcs_bmc_cdev_ops *ops; +}; + struct kcs_bmc_client_ops { int (*event)(struct kcs_bmc_client *client); }; @@ -20,6 +31,9 @@ struct kcs_bmc_client { struct kcs_bmc_device *dev; }; +int kcs_bmc_register_cdev(struct kcs_bmc_cdev *cdev); +int kcs_bmc_unregister_cdev(struct kcs_bmc_cdev *cdev); + int kcs_bmc_enable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client); void kcs_bmc_disable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client); From patchwork Fri Mar 19 06:27:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455609 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=HyyBNk57; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=TW01AIRC; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vCn6sQPz9sWj for ; Fri, 19 Mar 2021 17:30:45 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233973AbhCSGaN (ORCPT ); Fri, 19 Mar 2021 02:30:13 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:54123 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234118AbhCSG3n (ORCPT ); Fri, 19 Mar 2021 02:29:43 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id 0492D580A7C; Fri, 19 Mar 2021 02:29:43 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:29:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=sxfUwUAfmIiTx B4oKLrv/6yomvqUrbaDxVT8XNHcrM0=; b=HyyBNk57/2Mr3rilrBFvl6jom5mj2 ADJkN9TJFFE7IN/rxuB90/mchmtEXkuw7mZX1TpuhAP312fQHrNjtcxrgvBpMfaz 8A+6whmB7HTA9qmvxdzkN+E5hyjv8f6rIeW2PN5seEOIewyRe3sgt5wiJUpSMsi5 ugYy9iDnh6y/f8ZwcJyVGJI+cvfSUisqvc0mD2/3K14asXOaJiUDL0UltWfbcgOB Fpv3ZARkuHM1ZJR0a1MJ161X2UAcD0z6WPCgIf83p0W6egbMxuO54Eq0tMsw406D L2h/Vex9B2IaOvOsC7bEpwnFGhLgWLtOD/O3WCGLIndxt7tv4QhPV0qLg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=sxfUwUAfmIiTxB4oKLrv/6yomvqUrbaDxVT8XNHcrM0=; b=TW01AIRC iRuEDFvAdj4JS4jD5lm3Ejct5/YlSK7xewY1U2TrKYpn1r+wg+5RiIuT7WXAq09g zkV6Ds2eGIjLIDtyMlvrZ+UdFf/rBAqm0vYXLJgms9v/NO4Ibv/llxQ8hPwLG3Uv vIUzGkhjGmx6Tci6Y6/U0asToJe2QgIzWChYOGKjACOiJ6NKNORRYmfyYJJeJ80T +IhDUB8rYOKRRJt6zNJLRb4/rjBHOmXZPTSKYbtb3s2ti2+XTAxwH34PYmLQs0NF WlQIB1Sh7vFq+t8aKOGCAJSgYcZua3B1dkamBuU/wnR99RT/+ArFhX39bkkK4mmj YMxKUbOLTpZxig== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppeduudekrddvuddtrddukedurdeh heenucevlhhushhtvghrufhiiigvpeehnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnh gurhgvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 4CED5240057; Fri, 19 Mar 2021 02:29:37 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, chiawei_wang@aspeedtech.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 14/21] ipmi: kcs_bmc: Allow clients to control KCS IRQ state Date: Fri, 19 Mar 2021 16:57:45 +1030 Message-Id: <20210319062752.145730-14-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Add a mechanism for controlling whether the client associated with a KCS device will receive Input Buffer Full (IBF) and Output Buffer Empty (OBE) events. This enables an abstract implementation of poll() for KCS devices. A wart in the implementation is that the ASPEED KCS devices don't support an OBE interrupt for the BMC. Instead we pretend it has one by polling the status register waiting for the Output Buffer Full (OBF) bit to clear, and generating an event when OBE is observed. Signed-off-by: Andrew Jeffery --- drivers/char/ipmi/kcs_bmc.c | 6 ++ drivers/char/ipmi/kcs_bmc.h | 3 + drivers/char/ipmi/kcs_bmc_aspeed.c | 150 ++++++++++++++++++---------- drivers/char/ipmi/kcs_bmc_client.h | 2 + drivers/char/ipmi/kcs_bmc_device.h | 1 + drivers/char/ipmi/kcs_bmc_npcm7xx.c | 25 ++++- 6 files changed, 130 insertions(+), 57 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index 694db6ee2a92..05bbb72418b2 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -184,6 +184,12 @@ int kcs_bmc_unregister_cdev(struct kcs_bmc_cdev *cdev) } EXPORT_SYMBOL(kcs_bmc_unregister_cdev); +void kcs_bmc_update_event_mask(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 events) +{ + kcs_bmc->ops->irq_mask_update(kcs_bmc, mask, events); +} +EXPORT_SYMBOL(kcs_bmc_update_event_mask); + MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Haiyue Wang "); MODULE_AUTHOR("Andrew Jeffery "); diff --git a/drivers/char/ipmi/kcs_bmc.h b/drivers/char/ipmi/kcs_bmc.h index 5deb9a0b8e60..11fff935218c 100644 --- a/drivers/char/ipmi/kcs_bmc.h +++ b/drivers/char/ipmi/kcs_bmc.h @@ -11,6 +11,9 @@ #define KCS_BMC_EVENT_NONE 0 #define KCS_BMC_EVENT_HANDLED 1 +#define KCS_BMC_EVENT_TYPE_OBE BIT(0) +#define KCS_BMC_EVENT_TYPE_IBF BIT(1) + #define KCS_BMC_STR_OBF BIT(0) #define KCS_BMC_STR_IBF BIT(1) #define KCS_BMC_STR_CMD_DAT BIT(3) diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 6f26e7366c0b..5f26471c038c 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -60,10 +60,18 @@ #define LPC_ODR4 0x118 #define LPC_STR4 0x11C +#define OBE_POLL_PERIOD (HZ / 2) + struct aspeed_kcs_bmc { struct kcs_bmc_device kcs_bmc; struct regmap *map; + + struct { + spinlock_t lock; + bool remove; + struct timer_list timer; + } obe; }; struct aspeed_kcs_of_ops { @@ -159,68 +167,89 @@ static void aspeed_kcs_enable_channel(struct kcs_bmc_device *kcs_bmc, bool enabl switch (kcs_bmc->channel) { case 1: - if (enable) { - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF1, LPC_HICR2_IBFIF1); - regmap_update_bits(priv->map, LPC_HICR0, - LPC_HICR0_LPC1E, LPC_HICR0_LPC1E); - } else { - regmap_update_bits(priv->map, LPC_HICR0, - LPC_HICR0_LPC1E, 0); - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF1, 0); - } - break; - + regmap_update_bits(priv->map, LPC_HICR0, LPC_HICR0_LPC1E, enable * LPC_HICR0_LPC1E); + return; case 2: - if (enable) { - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF2, LPC_HICR2_IBFIF2); - regmap_update_bits(priv->map, LPC_HICR0, - LPC_HICR0_LPC2E, LPC_HICR0_LPC2E); - } else { - regmap_update_bits(priv->map, LPC_HICR0, - LPC_HICR0_LPC2E, 0); - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF2, 0); - } - break; - + regmap_update_bits(priv->map, LPC_HICR0, LPC_HICR0_LPC2E, enable * LPC_HICR0_LPC2E); + return; case 3: - if (enable) { - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF3, LPC_HICR2_IBFIF3); - regmap_update_bits(priv->map, LPC_HICR0, - LPC_HICR0_LPC3E, LPC_HICR0_LPC3E); - regmap_update_bits(priv->map, LPC_HICR4, - LPC_HICR4_KCSENBL, LPC_HICR4_KCSENBL); - } else { - regmap_update_bits(priv->map, LPC_HICR0, - LPC_HICR0_LPC3E, 0); - regmap_update_bits(priv->map, LPC_HICR4, - LPC_HICR4_KCSENBL, 0); - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF3, 0); - } - break; - + regmap_update_bits(priv->map, LPC_HICR0, LPC_HICR0_LPC3E, enable * LPC_HICR0_LPC3E); + regmap_update_bits(priv->map, LPC_HICR4, + LPC_HICR4_KCSENBL, enable * LPC_HICR4_KCSENBL); + return; case 4: - if (enable) - regmap_update_bits(priv->map, LPC_HICRB, - LPC_HICRB_IBFIF4 | LPC_HICRB_LPC4E, - LPC_HICRB_IBFIF4 | LPC_HICRB_LPC4E); + regmap_update_bits(priv->map, LPC_HICRB, LPC_HICRB_LPC4E, enable * LPC_HICRB_LPC4E); + return; + default: + pr_warn("%s: Unsupported channel: %d", __func__, kcs_bmc->channel); + return; + } +} + +static void aspeed_kcs_check_obe(struct timer_list *timer) +{ + struct aspeed_kcs_bmc *priv = container_of(timer, struct aspeed_kcs_bmc, obe.timer); + unsigned long flags; + u8 str; + + spin_lock_irqsave(&priv->obe.lock, flags); + if (priv->obe.remove) { + spin_unlock_irqrestore(&priv->obe.lock, flags); + return; + } + + str = aspeed_kcs_inb(&priv->kcs_bmc, priv->kcs_bmc.ioreg.str); + if (str & KCS_BMC_STR_OBF) { + mod_timer(timer, jiffies + OBE_POLL_PERIOD); + spin_unlock_irqrestore(&priv->obe.lock, flags); + return; + } + spin_unlock_irqrestore(&priv->obe.lock, flags); + + kcs_bmc_handle_event(&priv->kcs_bmc); +} + +static void aspeed_kcs_irq_mask_update(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 state) +{ + struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); + + /* We don't have an OBE IRQ, emulate it */ + if (KCS_BMC_EVENT_TYPE_OBE & mask) { + if (KCS_BMC_EVENT_TYPE_OBE & state) + mod_timer(&priv->obe.timer, jiffies + OBE_POLL_PERIOD); else - regmap_update_bits(priv->map, LPC_HICRB, - LPC_HICRB_IBFIF4 | LPC_HICRB_LPC4E, - 0); - break; + del_timer(&priv->obe.timer); + } - default: - break; + if (KCS_BMC_EVENT_TYPE_IBF & mask) { + const bool enable = !!(KCS_BMC_EVENT_TYPE_IBF & state); + + switch (kcs_bmc->channel) { + case 1: + regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIF1, + enable * LPC_HICR2_IBFIF1); + return; + case 2: + regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIF2, + enable * LPC_HICR2_IBFIF2); + return; + case 3: + regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIF3, + enable * LPC_HICR2_IBFIF3); + return; + case 4: + regmap_update_bits(priv->map, LPC_HICRB, LPC_HICRB_IBFIF4, + enable * LPC_HICRB_IBFIF4); + return; + default: + pr_warn("%s: Unsupported channel: %d", __func__, kcs_bmc->channel); + return; + } } } static const struct kcs_bmc_device_ops aspeed_kcs_ops = { + .irq_mask_update = aspeed_kcs_irq_mask_update, .io_inputb = aspeed_kcs_inb, .io_outputb = aspeed_kcs_outb, .io_updateb = aspeed_kcs_updateb, @@ -378,6 +407,10 @@ static int aspeed_kcs_probe(struct platform_device *pdev) return -ENODEV; } + spin_lock_init(&priv->obe.lock); + priv->obe.remove = false; + timer_setup(&priv->obe.timer, aspeed_kcs_check_obe, 0); + aspeed_kcs_set_address(kcs_bmc, addr); rc = aspeed_kcs_config_irq(kcs_bmc, pdev); @@ -386,6 +419,8 @@ static int aspeed_kcs_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); + aspeed_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), + KCS_BMC_EVENT_TYPE_IBF); aspeed_kcs_enable_channel(kcs_bmc, true); rc = kcs_bmc_add_device(&priv->kcs_bmc); @@ -404,6 +439,15 @@ static int aspeed_kcs_remove(struct platform_device *pdev) kcs_bmc_remove_device(kcs_bmc); + aspeed_kcs_enable_channel(kcs_bmc, false); + aspeed_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), 0); + + /* Make sure it's proper dead */ + spin_lock_irq(&priv->obe.lock); + priv->obe.remove = true; + spin_unlock_irq(&priv->obe.lock); + del_timer_sync(&priv->obe.timer); + return 0; } diff --git a/drivers/char/ipmi/kcs_bmc_client.h b/drivers/char/ipmi/kcs_bmc_client.h index d0a7404ff584..456796da33de 100644 --- a/drivers/char/ipmi/kcs_bmc_client.h +++ b/drivers/char/ipmi/kcs_bmc_client.h @@ -37,6 +37,8 @@ int kcs_bmc_unregister_cdev(struct kcs_bmc_cdev *cdev); int kcs_bmc_enable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client); void kcs_bmc_disable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client); +void kcs_bmc_update_event_mask(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 events); + u8 kcs_bmc_read_data(struct kcs_bmc_device *kcs_bmc); void kcs_bmc_write_data(struct kcs_bmc_device *kcs_bmc, u8 data); u8 kcs_bmc_read_status(struct kcs_bmc_device *kcs_bmc); diff --git a/drivers/char/ipmi/kcs_bmc_device.h b/drivers/char/ipmi/kcs_bmc_device.h index 57b7174b2bac..f1ca8912496a 100644 --- a/drivers/char/ipmi/kcs_bmc_device.h +++ b/drivers/char/ipmi/kcs_bmc_device.h @@ -7,6 +7,7 @@ #include "kcs_bmc.h" struct kcs_bmc_device_ops { + void (*irq_mask_update)(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 enable); u8 (*io_inputb)(struct kcs_bmc_device *kcs_bmc, u32 reg); void (*io_outputb)(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 b); void (*io_updateb)(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 mask, u8 b); diff --git a/drivers/char/ipmi/kcs_bmc_npcm7xx.c b/drivers/char/ipmi/kcs_bmc_npcm7xx.c index dce93ec895fc..c2032728a03d 100644 --- a/drivers/char/ipmi/kcs_bmc_npcm7xx.c +++ b/drivers/char/ipmi/kcs_bmc_npcm7xx.c @@ -38,6 +38,7 @@ #define KCS2CTL 0x2A #define KCS3CTL 0x3C #define KCS_CTL_IBFIE BIT(0) +#define KCS_CTL_OBEIE BIT(0) #define KCS1IE 0x1C #define KCS2IE 0x2E @@ -117,13 +118,23 @@ static void npcm7xx_kcs_enable_channel(struct kcs_bmc_device *kcs_bmc, bool enab { struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); - regmap_update_bits(priv->map, priv->reg->ctl, KCS_CTL_IBFIE, - enable ? KCS_CTL_IBFIE : 0); - regmap_update_bits(priv->map, priv->reg->ie, KCS_IE_IRQE | KCS_IE_HIRQE, enable ? KCS_IE_IRQE | KCS_IE_HIRQE : 0); } +static void npcm7xx_kcs_irq_mask_update(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 state) +{ + struct npcm7xx_kcs_bmc *priv = to_npcm7xx_kcs_bmc(kcs_bmc); + + if (KCS_BMC_EVENT_TYPE_OBE & mask) + regmap_update_bits(priv->map, priv->reg->ctl, KCS_CTL_OBEIE, + !!(KCS_BMC_EVENT_TYPE_OBE & state) * KCS_CTL_OBEIE); + + if (KCS_BMC_EVENT_TYPE_IBF & mask) + regmap_update_bits(priv->map, priv->reg->ctl, KCS_CTL_IBFIE, + !!(KCS_BMC_EVENT_TYPE_IBF & state) * KCS_CTL_IBFIE); +} + static irqreturn_t npcm7xx_kcs_irq(int irq, void *arg) { struct kcs_bmc_device *kcs_bmc = arg; @@ -151,6 +162,7 @@ static int npcm7xx_kcs_config_irq(struct kcs_bmc_device *kcs_bmc, } static const struct kcs_bmc_device_ops npcm7xx_kcs_ops = { + .irq_mask_update = npcm7xx_kcs_irq_mask_update, .io_inputb = npcm7xx_kcs_inb, .io_outputb = npcm7xx_kcs_outb, .io_updateb = npcm7xx_kcs_updateb, @@ -191,11 +203,13 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); - npcm7xx_kcs_enable_channel(kcs_bmc, true); rc = npcm7xx_kcs_config_irq(kcs_bmc, pdev); if (rc) return rc; + npcm7xx_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), + KCS_BMC_EVENT_TYPE_IBF); + npcm7xx_kcs_enable_channel(kcs_bmc, true); pr_info("channel=%u idr=0x%x odr=0x%x str=0x%x\n", chan, @@ -211,6 +225,9 @@ static int npcm7xx_kcs_remove(struct platform_device *pdev) kcs_bmc_remove_device(kcs_bmc); + npcm7xx_kcs_enable_channel(kcs_bmc, false); + npcm7xx_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), 0); + return 0; } From patchwork Fri Mar 19 06:27:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455608 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=N/2IQwUm; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=haqExUDw; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vCn1qdFz9sWF for ; Fri, 19 Mar 2021 17:30:45 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234120AbhCSGaP (ORCPT ); Fri, 19 Mar 2021 02:30:15 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:58635 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234139AbhCSG3t (ORCPT ); Fri, 19 Mar 2021 02:29:49 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id 15853580A7D; Fri, 19 Mar 2021 02:29:49 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:29:49 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=kc6gjs9yqWDoK Csi1TqrIxa0TgkKoxNCj8JuwJy41yE=; b=N/2IQwUm/CCNKscarNRWoK5srrw7l 3KWQ3Tyg74Tn+7ffkq+Dt9PBtBVJdot9m4eAUXh0hQEr2wKUIpERKmaTtX08FCLx iVOv/+XpsQTpyTgpM9WtkoPoSBRxzIc1u35sw7VAGnjqfoum2ZwC+uh0nnYhcRgb OujilZrV7fTzlSM/YeoV7x5EE67Ma143X5BnwZbeYE8tC5AKekq6EKGBNmuFrhSR H6OptXqTXjB78cuh5syKoe17Jk4T/HVJvKitPTEOE3l2tZdIyNjG/phh351iSA3M Uf4SI6/3pqYnMdf7faPOrPp11RkU0trjk1G/18bYGKimkLGyszIhES9wg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=kc6gjs9yqWDoKCsi1TqrIxa0TgkKoxNCj8JuwJy41yE=; b=haqExUDw OATLF5XCK885i35LdG3y/jDwNt29M1tpvQjUYS1QyLTNlVmQiOjdDB4B5jHRubA2 GlbG5Qghw+zLKFYXrplaOdShgJ0x31R1V0FMz0cZ6hSOVhojNvhrRHdHGbzyni8a HBbu9Z8sjEioyunkNJdOLU6K3wPBxuCb+cdtowDF+WNCureMEZ6ZVF5+KXU+PtBq adDAXIAfpsn/HKosine81JqokZfYdqnf11x1oyEf746IrBROJagWN5ORB2KLhNmz SvzPziUKgNN7d5gefCNRdEKc1azOVGdQg532FHiVN3phORGMbGmuLb1dYDTSqTX+ up/sjUi4MH79fQ== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppeduudekrddvuddtrddukedurdeh heenucevlhhushhtvghrufhiiigvpeeinecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnh gurhgvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 67BF0240057; Fri, 19 Mar 2021 02:29:43 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, chiawei_wang@aspeedtech.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 15/21] ipmi: kcs_bmc: Don't enforce single-open policy in the kernel Date: Fri, 19 Mar 2021 16:57:46 +1030 Message-Id: <20210319062752.145730-15-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Soon it will be possible for one KCS device to have multiple associated chardevs exposed to userspace (for IPMI and raw-style access). However, don't prevent userspace from: 1. Opening more than one chardev at a time, or 2. Opening the same chardev more than once. System behaviour is undefined for both classes of multiple access, so userspace must manage itself accordingly. The implementation delivers IBF and OBF events to the first chardev client to associate with the KCS device. An open on a related chardev cannot associate its client with the KCS device and so will not receive notification of events. However, any fd on any chardev may race their accesses to the data and status registers. Signed-off-by: Andrew Jeffery --- drivers/char/ipmi/kcs_bmc.c | 34 ++++++++++------------------- drivers/char/ipmi/kcs_bmc_aspeed.c | 3 +-- drivers/char/ipmi/kcs_bmc_npcm7xx.c | 3 +-- 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index 05bbb72418b2..2fafa9541934 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -55,24 +55,12 @@ EXPORT_SYMBOL(kcs_bmc_update_status); int kcs_bmc_handle_event(struct kcs_bmc_device *kcs_bmc) { struct kcs_bmc_client *client; - int rc; + int rc = KCS_BMC_EVENT_NONE; spin_lock(&kcs_bmc->lock); client = kcs_bmc->client; - if (client) { + if (!WARN_ON_ONCE(!client)) rc = client->ops->event(client); - } else { - u8 status; - - status = kcs_bmc_read_status(kcs_bmc); - if (status & KCS_BMC_STR_IBF) { - /* Ack the event by reading the data */ - kcs_bmc_read_data(kcs_bmc); - rc = KCS_BMC_EVENT_HANDLED; - } else { - rc = KCS_BMC_EVENT_NONE; - } - } spin_unlock(&kcs_bmc->lock); return rc; @@ -81,26 +69,28 @@ EXPORT_SYMBOL(kcs_bmc_handle_event); int kcs_bmc_enable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client) { - int rc; - spin_lock_irq(&kcs_bmc->lock); - if (kcs_bmc->client) { - rc = -EBUSY; - } else { + if (!kcs_bmc->client) { + u8 mask = KCS_BMC_EVENT_TYPE_IBF; + kcs_bmc->client = client; - rc = 0; + kcs_bmc_update_event_mask(kcs_bmc, mask, mask); } spin_unlock_irq(&kcs_bmc->lock); - return rc; + return 0; } EXPORT_SYMBOL(kcs_bmc_enable_device); void kcs_bmc_disable_device(struct kcs_bmc_device *kcs_bmc, struct kcs_bmc_client *client) { spin_lock_irq(&kcs_bmc->lock); - if (client == kcs_bmc->client) + if (client == kcs_bmc->client) { + u8 mask = KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE; + + kcs_bmc_update_event_mask(kcs_bmc, mask, 0); kcs_bmc->client = NULL; + } spin_unlock_irq(&kcs_bmc->lock); } EXPORT_SYMBOL(kcs_bmc_disable_device); diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 5f26471c038c..271845eb2e26 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -419,8 +419,7 @@ static int aspeed_kcs_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); - aspeed_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), - KCS_BMC_EVENT_TYPE_IBF); + aspeed_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), 0); aspeed_kcs_enable_channel(kcs_bmc, true); rc = kcs_bmc_add_device(&priv->kcs_bmc); diff --git a/drivers/char/ipmi/kcs_bmc_npcm7xx.c b/drivers/char/ipmi/kcs_bmc_npcm7xx.c index c2032728a03d..fdf35cad2eba 100644 --- a/drivers/char/ipmi/kcs_bmc_npcm7xx.c +++ b/drivers/char/ipmi/kcs_bmc_npcm7xx.c @@ -207,8 +207,7 @@ static int npcm7xx_kcs_probe(struct platform_device *pdev) if (rc) return rc; - npcm7xx_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), - KCS_BMC_EVENT_TYPE_IBF); + npcm7xx_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), 0); npcm7xx_kcs_enable_channel(kcs_bmc, true); pr_info("channel=%u idr=0x%x odr=0x%x str=0x%x\n", From patchwork Fri Mar 19 06:27:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455613 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=q3XkDkYW; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=J304m5Tr; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vCv2Rgzz9sjD for ; Fri, 19 Mar 2021 17:30:51 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234130AbhCSGaQ (ORCPT ); Fri, 19 Mar 2021 02:30:16 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:38181 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234197AbhCSG3z (ORCPT ); Fri, 19 Mar 2021 02:29:55 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id 119DC580A81; Fri, 19 Mar 2021 02:29:55 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:29:55 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=aQnNHewa5jTnB GjGVTD5mvjVD6p5J2c954frqWDzHlE=; b=q3XkDkYWzcRoGHuiO64SEX0218rb5 kyZ6m4h1iTXi61Yp4N7fUMoAR0BsBlm6tHdomMm3fSDvGsH25J5V2KpOdff0gGYx yEUpoxJVmn5AtwTsLhHpfXfbTmn8Kjtl6WPNOYwUjMscFbdhabR+1ssGXh0zUotL Er8EBGr7Om+ELe3XKZM0f8zAfSCKxNUuFYNRfe2Q7YaEZA2Tj62qsV51CGPvpzM3 /zh+7dWgHZYZxD/Jqb/V2deKI5HepQifCUxwWHUzro6sooyICt2PayezGT4Dcsh7 3MCej7jtFb+kTfBJAkyJyAy3MYuA0yzhJ73H5X6qvqRgAN/IsR/v0FJbQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=aQnNHewa5jTnBGjGVTD5mvjVD6p5J2c954frqWDzHlE=; b=J304m5Tr VWKuub7XG2k6keN4zBXCBWnY94BvFWaE/fCB4G35m6VhfWyFXGhn9n+TxfJYQNJI 7dKqjyTVgcyOXR85BdZ95TM8tdRlmj5QX1GzNupSPejLfeME7+XNmmhYa0xMQmGN MIioB4MwP37840Zfpzpz2VrO+LzMLGAgsEmFObIt9gLyIwsJicjUXXAcjEA0DXfG +DzwQbZoEQwjae+xXuKhAXxywslY4RONqN/MkNJjkoL0tyeWdcZaudO8Ael1gV9r VPtji1T1vZAr6j3umMiZ4QP0gx4tDoV5cbGZ796xDvfw8+6Q7JoStypM7D+4gKu8 SLrDvSnIIyAEDQ== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepuefhtefhudeufeehffeffeetieeufe duleevgfekteefteekleetffehjeeukeehnecuffhomhgrihhnpehgihhthhhusgdrtgho mhenucfkphepuddukedrvddutddrudekuddrheehnecuvehluhhsthgvrhfuihiivgeptd enucfrrghrrghmpehmrghilhhfrhhomheprghnughrvgifsegrjhdrihgurdgruh X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 78253240057; Fri, 19 Mar 2021 02:29:49 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, chiawei_wang@aspeedtech.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 16/21] ipmi: kcs_bmc: Add a "raw" character device interface Date: Fri, 19 Mar 2021 16:57:47 +1030 Message-Id: <20210319062752.145730-16-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org The existing IPMI chardev encodes IPMI behaviours as the name suggests. However, KCS devices are useful beyond IPMI (or keyboards), as they provide a means to generate IRQs and exchange arbitrary data between a BMC and its host system. Implement a "raw" KCS character device that exposes the IDR, ODR and STR registers to userspace via read() and write() implemented on a character device: +--------+--------+---------+ | Offset | read() | write() | +--------+--------+---------+ | 0 | IDR | ODR | +--------+--------+---------+ | 1 | STR | STR | +--------+--------+---------+ This interface allows userspace to implement arbitrary (though somewhat inefficient) protocols for exchanging information between a BMC and host firmware. Conceptually the KCS interface can be used as an out-of-band machanism for interrupt-signaled control messages while bulk data transfers occur over more appropriate interfaces between the BMC and the host (which may lack their own interrupt mechanism, e.g. LPC FW cycles). poll() is provided, which will wait for IBF or OBE conditions for data reads and writes respectively. Reads of STR on its own never blocks, though accessing both offsets in the one system call may block if the data registers are not ready. Signed-off-by: Andrew Jeffery --- Documentation/ABI/testing/dev-raw-kcs | 25 ++ drivers/char/ipmi/Kconfig | 17 + drivers/char/ipmi/Makefile | 1 + drivers/char/ipmi/kcs_bmc_cdev_raw.c | 443 ++++++++++++++++++++++++++ 4 files changed, 486 insertions(+) create mode 100644 Documentation/ABI/testing/dev-raw-kcs create mode 100644 drivers/char/ipmi/kcs_bmc_cdev_raw.c diff --git a/Documentation/ABI/testing/dev-raw-kcs b/Documentation/ABI/testing/dev-raw-kcs new file mode 100644 index 000000000000..06e7e2071562 --- /dev/null +++ b/Documentation/ABI/testing/dev-raw-kcs @@ -0,0 +1,25 @@ +What: /dev/raw-kcs* +Date: 2021-02-15 +KernelVersion: 5.13 +Contact: openbmc@lists.ozlabs.org +Contact: openipmi-developer@lists.sourceforge.net +Contact: Andrew Jeffery +Description: ``/dev/raw-kcs*`` exposes to userspace the data and + status registers of Keyboard-Controller-Style (KCS) IPMI + interfaces via read() and write() syscalls. Direct + exposure of the data and status registers enables + inefficient but arbitrary protocols to be implemented + over the device. A typical approach is to use KCS + devices for out-of-band signalling for bulk data + transfers over other interfaces between a Baseboard + Management Controller and its host. + + +--------+--------+---------+ + | Offset | read() | write() | + +--------+--------+---------+ + | 0 | IDR | ODR | + +--------+--------+---------+ + | 1 | STR | STR | + +--------+--------+---------+ + +Users: libmctp: https://github.com/openbmc/libmctp diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig index bc5f81899b62..273ac1a1f870 100644 --- a/drivers/char/ipmi/Kconfig +++ b/drivers/char/ipmi/Kconfig @@ -137,6 +137,23 @@ config IPMI_KCS_BMC_CDEV_IPMI This support is also available as a module. The module will be called kcs_bmc_cdev_ipmi. +config IPMI_KCS_BMC_CDEV_RAW + depends on IPMI_KCS_BMC + tristate "Raw character device interface for BMC KCS devices" + help + Provides a BMC-side character device directly exposing the + data and status registers of a KCS device to userspace. While + KCS devices are commonly used to implement IPMI message + passing, they provide a general interface for exchange of + interrupts, data and status information between the BMC and + its host. + + Say YES if you wish to use the KCS devices to implement + protocols that are not IPMI. + + This support is also available as a module. The module will be + called kcs_bmc_cdev_raw. + config ASPEED_BT_IPMI_BMC depends on ARCH_ASPEED || COMPILE_TEST depends on REGMAP && REGMAP_MMIO && MFD_SYSCON diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile index fcfa676afddb..c8cc248ddd90 100644 --- a/drivers/char/ipmi/Makefile +++ b/drivers/char/ipmi/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o obj-$(CONFIG_IPMI_KCS_BMC) += kcs_bmc.o obj-$(CONFIG_IPMI_KCS_BMC_CDEV_IPMI) += kcs_bmc_cdev_ipmi.o +obj-$(CONFIG_IPMI_KCS_BMC_CDEV_RAW) += kcs_bmc_cdev_raw.o obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o obj-$(CONFIG_ASPEED_KCS_IPMI_BMC) += kcs_bmc_aspeed.o obj-$(CONFIG_NPCM7XX_KCS_IPMI_BMC) += kcs_bmc_npcm7xx.o diff --git a/drivers/char/ipmi/kcs_bmc_cdev_raw.c b/drivers/char/ipmi/kcs_bmc_cdev_raw.c new file mode 100644 index 000000000000..bdd258648c8e --- /dev/null +++ b/drivers/char/ipmi/kcs_bmc_cdev_raw.c @@ -0,0 +1,443 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Copyright (c) 2021 IBM Corp. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kcs_bmc_client.h" + +#define DEVICE_NAME "raw-kcs" + +struct kcs_bmc_raw { + struct list_head entry; + + struct kcs_bmc_client client; + + wait_queue_head_t queue; + u8 events; + bool writable; + bool readable; + u8 idr; + + struct miscdevice miscdev; +}; + +static inline struct kcs_bmc_raw *client_to_kcs_bmc_raw(struct kcs_bmc_client *client) +{ + return container_of(client, struct kcs_bmc_raw, client); +} + +/* Call under priv->queue.lock */ +static void kcs_bmc_raw_update_event_mask(struct kcs_bmc_raw *priv, u8 mask, u8 state) +{ + kcs_bmc_update_event_mask(priv->client.dev, mask, state); + priv->events &= ~mask; + priv->events |= state & mask; +} + +static int kcs_bmc_raw_event(struct kcs_bmc_client *client) +{ + struct kcs_bmc_raw *priv; + struct device *dev; + u8 status, handled; + + priv = client_to_kcs_bmc_raw(client); + dev = priv->miscdev.this_device; + + spin_lock(&priv->queue.lock); + + status = kcs_bmc_read_status(client->dev); + handled = 0; + + if ((priv->events & KCS_BMC_EVENT_TYPE_IBF) && (status & KCS_BMC_STR_IBF)) { + if (priv->readable) + dev_err(dev, "Storm brewing!"); + + dev_dbg(dev, "Disabling IDR events for back-pressure\n"); + kcs_bmc_raw_update_event_mask(priv, KCS_BMC_EVENT_TYPE_IBF, 0); + priv->idr = kcs_bmc_read_data(client->dev); + priv->readable = true; + + dev_dbg(dev, "IDR read, waking waiters\n"); + wake_up_locked(&priv->queue); + + handled |= KCS_BMC_EVENT_TYPE_IBF; + } + + if ((priv->events & KCS_BMC_EVENT_TYPE_OBE) && !(status & KCS_BMC_STR_OBF)) { + kcs_bmc_raw_update_event_mask(priv, KCS_BMC_EVENT_TYPE_OBE, 0); + priv->writable = true; + + dev_dbg(dev, "ODR writable, waking waiters\n"); + wake_up_locked(&priv->queue); + + handled |= KCS_BMC_EVENT_TYPE_OBE; + } + + spin_unlock(&priv->queue.lock); + + return handled ? KCS_BMC_EVENT_HANDLED : KCS_BMC_EVENT_NONE; +} + +static const struct kcs_bmc_client_ops kcs_bmc_raw_client_ops = { + .event = kcs_bmc_raw_event, +}; + +static inline struct kcs_bmc_raw *file_to_kcs_bmc_raw(struct file *filp) +{ + return container_of(filp->private_data, struct kcs_bmc_raw, miscdev); +} + +static int kcs_bmc_raw_open(struct inode *inode, struct file *filp) +{ + struct kcs_bmc_raw *priv = file_to_kcs_bmc_raw(filp); + + return kcs_bmc_enable_device(priv->client.dev, &priv->client); +} + +static bool kcs_bmc_raw_prepare_obe(struct kcs_bmc_raw *priv) +{ + bool writable; + + /* Enable the OBE event so we can catch the host clearing OBF */ + kcs_bmc_raw_update_event_mask(priv, KCS_BMC_EVENT_TYPE_OBE, KCS_BMC_EVENT_TYPE_OBE); + + /* Now that we'll catch an OBE event, check if it's already occurred */ + writable = !(kcs_bmc_read_status(priv->client.dev) & KCS_BMC_STR_OBF); + + /* If OBF is clear we've missed the OBE event, so disable it */ + if (writable) + kcs_bmc_raw_update_event_mask(priv, KCS_BMC_EVENT_TYPE_OBE, 0); + + return writable; +} + +static __poll_t kcs_bmc_raw_poll(struct file *filp, poll_table *wait) +{ + struct kcs_bmc_raw *priv; + __poll_t events = 0; + + priv = file_to_kcs_bmc_raw(filp); + + poll_wait(filp, &priv->queue, wait); + + spin_lock_irq(&priv->queue.lock); + if (kcs_bmc_raw_prepare_obe(priv)) + events |= (EPOLLOUT | EPOLLWRNORM); + + if (priv->readable || (kcs_bmc_read_status(priv->client.dev) & KCS_BMC_STR_IBF)) + events |= (EPOLLIN | EPOLLRDNORM); + spin_unlock_irq(&priv->queue.lock); + + return events; +} + +static ssize_t kcs_bmc_raw_read(struct file *filp, char __user *buf, + size_t count, loff_t *ppos) +{ + struct kcs_bmc_device *kcs_bmc; + struct kcs_bmc_raw *priv; + bool read_idr, read_str; + struct device *dev; + u8 idr, str; + ssize_t rc; + + priv = file_to_kcs_bmc_raw(filp); + kcs_bmc = priv->client.dev; + dev = priv->miscdev.this_device; + + if (!count) + return 0; + + if (count > 2 || *ppos > 1) + return -EINVAL; + + if (*ppos + count > 2) + return -EINVAL; + + read_idr = (*ppos == 0); + read_str = (*ppos == 1) || (count == 2); + + spin_lock_irq(&priv->queue.lock); + if (read_idr) { + dev_dbg(dev, "Waiting for IBF\n"); + str = kcs_bmc_read_status(kcs_bmc); + if ((filp->f_flags & O_NONBLOCK) && (str & KCS_BMC_STR_IBF)) { + rc = -EWOULDBLOCK; + goto out; + } + + rc = wait_event_interruptible_locked(priv->queue, + priv->readable || (str & KCS_BMC_STR_IBF)); + if (rc < 0) + goto out; + + if (signal_pending(current)) { + dev_dbg(dev, "Interrupted waiting for IBF\n"); + rc = -EINTR; + goto out; + } + + /* + * Re-enable events prior to possible read of IDR (which clears + * IBF) to ensure we receive interrupts for subsequent writes + * to IDR. Writes to IDR by the host should not occur while IBF + * is set. + */ + dev_dbg(dev, "Woken by IBF, enabling IRQ\n"); + kcs_bmc_raw_update_event_mask(priv, KCS_BMC_EVENT_TYPE_IBF, + KCS_BMC_EVENT_TYPE_IBF); + + /* Read data out of IDR into internal storage if necessary */ + if (!priv->readable) { + WARN(!(str & KCS_BMC_STR_IBF), "Unknown reason for wakeup!"); + + priv->idr = kcs_bmc_read_data(kcs_bmc); + } + + /* Copy data from internal storage to userspace */ + idr = priv->idr; + + /* We're done consuming the internally stored value */ + priv->readable = false; + } + + if (read_str) { + str = kcs_bmc_read_status(kcs_bmc); + if (*ppos == 0 || priv->readable) + /* + * If we got this far with `*ppos == 0` then we've read + * data out of IDR, so set IBF when reporting back to + * userspace so userspace knows the IDR value is valid. + */ + str |= KCS_BMC_STR_IBF; + + dev_dbg(dev, "Read status 0x%x\n", str); + + } + + rc = count; +out: + spin_unlock_irq(&priv->queue.lock); + + if (rc < 0) + return rc; + + /* Now copy the data in to the userspace buffer */ + + if (read_idr) + if (copy_to_user(buf++, &idr, sizeof(idr))) + return -EFAULT; + + if (read_str) + if (copy_to_user(buf, &str, sizeof(str))) + return -EFAULT; + + return count; +} + +static ssize_t kcs_bmc_raw_write(struct file *filp, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct kcs_bmc_device *kcs_bmc; + bool write_odr, write_str; + struct kcs_bmc_raw *priv; + struct device *dev; + uint8_t data[2]; + ssize_t result; + u8 str; + + priv = file_to_kcs_bmc_raw(filp); + kcs_bmc = priv->client.dev; + dev = priv->miscdev.this_device; + + if (!count) + return count; + + if (count > 2) + return -EINVAL; + + if (*ppos >= 2) + return -EINVAL; + + if (*ppos + count > 2) + return -EINVAL; + + if (copy_from_user(data, buf, count)) + return -EFAULT; + + write_odr = (*ppos == 0); + write_str = (*ppos == 1) || (count == 2); + + spin_lock_irq(&priv->queue.lock); + + /* Always write status before data, we generate the SerIRQ by writing ODR */ + if (write_str) { + /* The index of STR in the userspace buffer depends on whether ODR is written */ + str = data[*ppos == 0]; + if (!(str & KCS_BMC_STR_OBF)) + dev_warn(dev, "Clearing OBF with status write: 0x%x\n", str); + dev_dbg(dev, "Writing status 0x%x\n", str); + kcs_bmc_write_status(kcs_bmc, str); + } + + if (write_odr) { + /* If we're writing ODR it's always the first byte in the buffer */ + u8 odr = data[0]; + + str = kcs_bmc_read_status(kcs_bmc); + if (str & KCS_BMC_STR_OBF) { + if (filp->f_flags & O_NONBLOCK) { + result = -EWOULDBLOCK; + goto out; + } + + priv->writable = kcs_bmc_raw_prepare_obe(priv); + + /* Now either OBF is already clear, or we'll get an OBE event to wake us */ + dev_dbg(dev, "Waiting for OBF to clear\n"); + wait_event_interruptible_locked(priv->queue, priv->writable); + + if (signal_pending(current)) { + kcs_bmc_raw_update_event_mask(priv, KCS_BMC_EVENT_TYPE_OBE, 0); + result = -EINTR; + goto out; + } + + WARN_ON(kcs_bmc_read_status(kcs_bmc) & KCS_BMC_STR_OBF); + } + + dev_dbg(dev, "Writing 0x%x to ODR\n", odr); + kcs_bmc_write_data(kcs_bmc, odr); + } + + result = count; +out: + spin_unlock_irq(&priv->queue.lock); + + return result; +} + +static int kcs_bmc_raw_release(struct inode *inode, struct file *filp) +{ + struct kcs_bmc_raw *priv = file_to_kcs_bmc_raw(filp); + + kcs_bmc_disable_device(priv->client.dev, &priv->client); + + return 0; +} + +static const struct file_operations kcs_bmc_raw_fops = { + .owner = THIS_MODULE, + .open = kcs_bmc_raw_open, + .llseek = no_seek_end_llseek, + .read = kcs_bmc_raw_read, + .write = kcs_bmc_raw_write, + .poll = kcs_bmc_raw_poll, + .release = kcs_bmc_raw_release, +}; + +static DEFINE_SPINLOCK(kcs_bmc_raw_instances_lock); +static LIST_HEAD(kcs_bmc_raw_instances); + +static int kcs_bmc_raw_attach_cdev(struct kcs_bmc_device *kcs_bmc) +{ + struct kcs_bmc_raw *priv; + int rc; + + priv = devm_kzalloc(kcs_bmc->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->client.dev = kcs_bmc; + priv->client.ops = &kcs_bmc_raw_client_ops; + + init_waitqueue_head(&priv->queue); + priv->writable = false; + priv->readable = false; + + priv->miscdev.minor = MISC_DYNAMIC_MINOR; + priv->miscdev.name = devm_kasprintf(kcs_bmc->dev, GFP_KERNEL, "%s%u", DEVICE_NAME, + kcs_bmc->channel); + if (!priv->miscdev.name) + return -EINVAL; + + priv->miscdev.fops = &kcs_bmc_raw_fops; + + /* Initialise our expected events. Listen for IBF but ignore OBE until necessary */ + kcs_bmc_raw_update_event_mask(priv, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), + KCS_BMC_EVENT_TYPE_IBF); + + rc = misc_register(&priv->miscdev); + if (rc) { + dev_err(kcs_bmc->dev, "Unable to register device\n"); + return rc; + } + + spin_lock_irq(&kcs_bmc_raw_instances_lock); + list_add(&priv->entry, &kcs_bmc_raw_instances); + spin_unlock_irq(&kcs_bmc_raw_instances_lock); + + dev_info(kcs_bmc->dev, "Initialised raw client for channel %d", kcs_bmc->channel); + + return 0; +} + +static int kcs_bmc_raw_detach_cdev(struct kcs_bmc_device *kcs_bmc) +{ + struct kcs_bmc_raw *priv = NULL, *pos; + + spin_lock_irq(&kcs_bmc_raw_instances_lock); + list_for_each_entry(pos, &kcs_bmc_raw_instances, entry) { + if (pos->client.dev == kcs_bmc) { + priv = pos; + list_del(&pos->entry); + break; + } + } + spin_unlock_irq(&kcs_bmc_raw_instances_lock); + + if (!priv) + return 0; + + misc_deregister(&priv->miscdev); + kcs_bmc_disable_device(kcs_bmc, &priv->client); + devm_kfree(priv->client.dev->dev, priv); + + return 0; +} + +static const struct kcs_bmc_cdev_ops kcs_bmc_raw_cdev_ops = { + .add_device = kcs_bmc_raw_attach_cdev, + .remove_device = kcs_bmc_raw_detach_cdev, +}; + +static struct kcs_bmc_cdev kcs_bmc_raw_cdev = { + .ops = &kcs_bmc_raw_cdev_ops, +}; + +static int kcs_bmc_raw_init(void) +{ + return kcs_bmc_register_cdev(&kcs_bmc_raw_cdev); +} +module_init(kcs_bmc_raw_init); + +static void kcs_bmc_raw_exit(void) +{ + int rc; + + rc = kcs_bmc_unregister_cdev(&kcs_bmc_raw_cdev); + if (rc) + pr_warn("Failed to remove KCS BMC client: %d", rc); +} +module_exit(kcs_bmc_raw_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Andrew Jeffery "); +MODULE_DESCRIPTION("Character device for raw access to a KCS device"); From patchwork Fri Mar 19 06:27:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455612 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=pLi8bbgz; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=FdRKCSBx; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vCt44B2z9sXM for ; Fri, 19 Mar 2021 17:30:50 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234138AbhCSGaR (ORCPT ); Fri, 19 Mar 2021 02:30:17 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:40449 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234210AbhCSGaB (ORCPT ); Fri, 19 Mar 2021 02:30:01 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id 09A5E580A82; Fri, 19 Mar 2021 02:30:01 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:30:01 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=5oH72UxBPItkL oFd6WxftMKWTkqg+oELaFqx3t9Isv4=; b=pLi8bbgzq0NFo60Xqb1DadiWgiMls Pb/V3jQk6WETOMg75ytPqsfh2mVvyUBbopCOUNqDSuzgSMl+KoLEhxiHCjegk5zM j8/Z1jI2CWansfOmHKshN6INyUlihKbvPaZXb9GJdnQ/G8NADL9VlyqbklDy0jMy CCllKEVFdIPL5bkQBKw3lTS0fZjNFReFLJPiN+LyefmkNbW6maLSOrOomUCbdWyG cb8ERlp8SK/W16HrTCNCI9mB/Iyzr/s0FUAY/FgRgJxeOU2ZgmExixEE/2P4/Xiz FxtSKXHT28+UkGdDhZEslhL3J8JU0mUUlUHX+5SEUVnEJYSbe7at8resA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=5oH72UxBPItkLoFd6WxftMKWTkqg+oELaFqx3t9Isv4=; b=FdRKCSBx Eahm0Ck+tyEfJ5SLdBOsRsYs+hKCUAVOPIfRWYgOWeP7dWWy8NKkiGq0VPsnxtVX IG9r92So6Biv8DXhzG9Xmuh0t226GKATX8C8GnFCBH7iUAw41EiDjArWJW45pLGY j36t8Qao3rykRrRXqr/QIGae8tQ1OO8Gs2zyY/GWxqa+w2KlEMWvZjtAOkr3pn/k xc632J6cF8gpQAnaSlr1OJB3+d5YVI1YdmDqXz4GqyxgEXeqROYt34518pkYX9Zb 73crvzj4qx5sqT88mRV6nExs7DHfjH1qHF6JK/jC4VZbm9BUjn9VtzJvKW45bZbc nw69al8hM1t/Dw== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepleeuvdevtdfggfeggffgueegvefghf ejfeeitddvhedvhfetffetffefiefhvedvnecuffhomhgrihhnpeguvghvihgtvghtrhgv vgdrohhrghenucfkphepuddukedrvddutddrudekuddrheehnecuvehluhhsthgvrhfuih iivgeptdenucfrrghrrghmpehmrghilhhfrhhomheprghnughrvgifsegrjhdrihgurdgr uh X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 720E0240057; Fri, 19 Mar 2021 02:29:55 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, chiawei_wang@aspeedtech.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 17/21] dt-bindings: ipmi: Convert ASPEED KCS binding to schema Date: Fri, 19 Mar 2021 16:57:48 +1030 Message-Id: <20210319062752.145730-17-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Given the deprecated binding, improve the ability to detect issues in the platform devicetrees. Further, a subsequent patch will introduce a new interrupts property for specifying SerIRQ behaviour, so convert before we do any further additions. Signed-off-by: Andrew Jeffery Reviewed-by: Rob Herring Reviewed-by: Zev Weiss --- .../bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml | 92 +++++++++++++++++++ .../bindings/ipmi/aspeed-kcs-bmc.txt | 33 ------- 2 files changed, 92 insertions(+), 33 deletions(-) create mode 100644 Documentation/devicetree/bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml delete mode 100644 Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt diff --git a/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml b/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml new file mode 100644 index 000000000000..697ca575454f --- /dev/null +++ b/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml @@ -0,0 +1,92 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-kcs-bmc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: ASPEED BMC KCS Devices + +maintainers: + - Andrew Jeffery + +description: | + The Aspeed BMC SoCs typically use the Keyboard-Controller-Style (KCS) + interfaces on the LPC bus for in-band IPMI communication with their host. + +properties: + compatible: + oneOf: + - description: Channel ID derived from reg + items: + enum: + - aspeed,ast2400-kcs-bmc-v2 + - aspeed,ast2500-kcs-bmc-v2 + - aspeed,ast2600-kcs-bmc + + - description: Old-style with explicit channel ID, no reg + deprecated: true + items: + enum: + - aspeed,ast2400-kcs-bmc + - aspeed,ast2500-kcs-bmc + + interrupts: + maxItems: 1 + + reg: + # maxItems: 3 + items: + - description: IDR register + - description: ODR register + - description: STR register + + aspeed,lpc-io-reg: + $ref: '/schemas/types.yaml#/definitions/uint32-array' + minItems: 1 + maxItems: 2 + description: | + The host CPU LPC IO data and status addresses for the device. For most + channels the status address is derived from the data address, but the + status address may be optionally provided. + + kcs_chan: + deprecated: true + $ref: '/schemas/types.yaml#/definitions/uint32' + description: The LPC channel number in the controller + + kcs_addr: + deprecated: true + $ref: '/schemas/types.yaml#/definitions/uint32' + description: The host CPU IO map address + +required: + - compatible + - interrupts + +additionalProperties: false + +allOf: + - if: + properties: + compatible: + contains: + enum: + - aspeed,ast2400-kcs-bmc + - aspeed,ast2500-kcs-bmc + then: + required: + - kcs_chan + - kcs_addr + else: + required: + - reg + - aspeed,lpc-io-reg + +examples: + - | + kcs3: kcs@24 { + compatible = "aspeed,ast2600-kcs-bmc"; + reg = <0x24 0x1>, <0x30 0x1>, <0x3c 0x1>; + aspeed,lpc-io-reg = <0xca2>; + interrupts = <8>; + }; diff --git a/Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt b/Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt deleted file mode 100644 index 193e71ca96b0..000000000000 --- a/Documentation/devicetree/bindings/ipmi/aspeed-kcs-bmc.txt +++ /dev/null @@ -1,33 +0,0 @@ -# Aspeed KCS (Keyboard Controller Style) IPMI interface - -The Aspeed SOCs (AST2400 and AST2500) are commonly used as BMCs -(Baseboard Management Controllers) and the KCS interface can be -used to perform in-band IPMI communication with their host. - -## v1 -Required properties: -- compatible : should be one of - "aspeed,ast2400-kcs-bmc" - "aspeed,ast2500-kcs-bmc" -- interrupts : interrupt generated by the controller -- kcs_chan : The LPC channel number in the controller -- kcs_addr : The host CPU IO map address - -## v2 -Required properties: -- compatible : should be one of - "aspeed,ast2400-kcs-bmc-v2" - "aspeed,ast2500-kcs-bmc-v2" -- reg : The address and size of the IDR, ODR and STR registers -- interrupts : interrupt generated by the controller -- aspeed,lpc-io-reg : The host CPU LPC IO address for the device - -Example: - - kcs3: kcs@24 { - compatible = "aspeed,ast2500-kcs-bmc-v2"; - reg = <0x24 0x1>, <0x30 0x1>, <0x3c 0x1>; - aspeed,lpc-reg = <0xca2>; - interrupts = <8>; - status = "okay"; - }; From patchwork Fri Mar 19 06:27:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455614 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=aKKxtWke; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=Pr7RXhlX; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vCz3XgCz9sW1 for ; Fri, 19 Mar 2021 17:30:55 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234153AbhCSGaT (ORCPT ); Fri, 19 Mar 2021 02:30:19 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:42085 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233919AbhCSGaH (ORCPT ); Fri, 19 Mar 2021 02:30:07 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id F2BC2580A85; Fri, 19 Mar 2021 02:30:06 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:30:06 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=QRDiTNGJwy42h fOUMjmwo2Lxr+h4OGF8vd82Dnei0yg=; b=aKKxtWkePJOP9OvXvaQqpJcmnBjD3 QLcjC6VhCh3bstlp3BeT8dbN3iw7wOTvgAlYrP6CwMllYSjzwKjhJ36Hdd5Z4zrJ hPQ23U1dSzbv4ZJn6jnw+brIZoeGIYnXok/vD0en4lYGWdbTFSiTC2r4hiTde26f i/eynZitLYZ92+VX1abe/ZHyvIk+zVaBcMGGmKsXMqbWH+eu3HCbUXy3j9AP8KJR Ae+cA5YZialf4g9cH4boJRbB38M9i3OfBzoPrDmqTFx1PiknNPDUMQiZ8Yh/aVVA JMSHz0r9Q7qCyFXW5wsDfdPtR3ZrOXOOtMOBb9zV6W28YnqDEOl3gaeVA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=QRDiTNGJwy42hfOUMjmwo2Lxr+h4OGF8vd82Dnei0yg=; b=Pr7RXhlX GP817mV0vLm6R7wuf2pubbnEco69DyrHkGoNglo5tOpBsp8bdcIlQOLq6jo2CZCc saiGrjX9dWQgvbgNPD5mhV4H5EkEaoBZhSJO7QzK4wcfT1O+VwVSNbYmLEZPVj02 XJppEoGHvzr5BFLDGRZhHVqXVnGUKUa3X3lmzSJLjQYS91eitGtAh8WDzR0U/JCz /Bqb8VDsmChgYXoIc/bjhmo7okuXweAUvC5+Pnnf4LWvhpJ+VWMjXHylfqJFC2jO 5o1CEyhEhGKrjiSCOrsfAZUBpQcGbgrp6rl/g4Ez/dzl2uIGHgBsrLKfBC7upJMv vTaZQVpUQBDasQ== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppeduudekrddvuddtrddukedurdeh heenucevlhhushhtvghrufhiiigvpeejnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnh gurhgvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 6B13A240057; Fri, 19 Mar 2021 02:30:01 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, chiawei_wang@aspeedtech.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 18/21] dt-bindings: ipmi: Add optional SerIRQ property to ASPEED KCS devices Date: Fri, 19 Mar 2021 16:57:49 +1030 Message-Id: <20210319062752.145730-18-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Allocating IO and IRQ resources to LPC devices is in-theory an operation for the host, however ASPEED don't appear to expose this capability outside the BMC (e.g. SuperIO). Instead, we are left with BMC-internal registers for managing these resources, so introduce a devicetree property for KCS devices to describe SerIRQ properties. Signed-off-by: Andrew Jeffery Reviewed-by: Rob Herring --- .../bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml b/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml index 697ca575454f..4ff6fabfcb30 100644 --- a/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml +++ b/Documentation/devicetree/bindings/ipmi/aspeed,ast2400-kcs-bmc.yaml @@ -49,6 +49,18 @@ properties: channels the status address is derived from the data address, but the status address may be optionally provided. + aspeed,lpc-interrupts: + $ref: "/schemas/types.yaml#/definitions/uint32-array" + minItems: 2 + maxItems: 2 + description: | + A 2-cell property expressing the LPC SerIRQ number and the interrupt + level/sense encoding (specified in the standard fashion). + + Note that the generated interrupt is issued from the BMC to the host, and + thus the target interrupt controller is not captured by the BMC's + devicetree. + kcs_chan: deprecated: true $ref: '/schemas/types.yaml#/definitions/uint32' @@ -84,9 +96,11 @@ allOf: examples: - | + #include kcs3: kcs@24 { compatible = "aspeed,ast2600-kcs-bmc"; reg = <0x24 0x1>, <0x30 0x1>, <0x3c 0x1>; aspeed,lpc-io-reg = <0xca2>; + aspeed,lpc-interrupts = <11 IRQ_TYPE_LEVEL_LOW>; interrupts = <8>; }; From patchwork Fri Mar 19 06:27:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455618 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=k4geBJdX; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=fuA2Ts/U; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vDP60fDz9sW1 for ; Fri, 19 Mar 2021 17:31:17 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234163AbhCSGaq (ORCPT ); Fri, 19 Mar 2021 02:30:46 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:60903 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234213AbhCSGaO (ORCPT ); Fri, 19 Mar 2021 02:30:14 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailnew.nyi.internal (Postfix) with ESMTP id 029ED580A7A; Fri, 19 Mar 2021 02:30:14 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute4.internal (MEProxy); Fri, 19 Mar 2021 02:30:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=uT25XJTeq1nXj HZ5voo0eEBIH5cJs0/xuiDMoEw+0Wo=; b=k4geBJdXyP2/tCgnt2v+wN2sRYY74 MCsF8iDNFGZNiMB41vfcZ6BMbk9MX7UfEWBkFhxMIYFnI287KgBV++GxtyCI6mlt dUpbVJ3shbbeiRwqRQ6vj1lUkgVBo81sc0hrwzDkq9iWEFQDnamHibwInoUIRZz3 2kndNojxp7MGJHoRj/gSfmq/sHGm4KLTUMh+DnYoguCAyUsQ8HykJXmswgnPU8BO qAxgw0QD+EMZh9JzKKQHXQGxhgVK3+S3+5YEbFSWJ4NNWub2qrJLMg5AzZJysl+W kkZyWxYyQNXVXuJkDkfMkKS5r6qbUn6YxcWzaySDtVZ1WM8ML7G8WMSRA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=uT25XJTeq1nXjHZ5voo0eEBIH5cJs0/xuiDMoEw+0Wo=; b=fuA2Ts/U xKKWN6cv2he/7vP2oDc6gAI85+y3/oTlecSpCRdAYm8aXCSVFrv0uQXzRtN9Qfe9 0/f8exITlFKH4cu2AUeOoL2Q/jJmJxpPHjCYMBeukLoMSQzc//0nYiGbiD7q8wCM JU/7JgSh6FTmR1KfA1Dkjc0liuiqdT2D+/tDNkrIwHuw2IcwFWzp8wp8VaKmoxm5 8rHhoNYe9rGHGo4uO80uVYiCJM/I9wAqrTBbSyWVEk3KAy5amXpNa6vtWxD+LR4z JxwlcS6ZvbHHdIZOY1IOEtWYkuzS9AHKe+077E3YRNFDOIdGMsngCiKgtb69zUWA rfwF4ug3BNXx5A== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppeduudekrddvuddtrddukedurdeh heenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnh gurhgvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 698AB24005B; Fri, 19 Mar 2021 02:30:07 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, chiawei_wang@aspeedtech.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 19/21] ipmi: kcs_bmc_aspeed: Implement KCS SerIRQ configuration Date: Fri, 19 Mar 2021 16:57:50 +1030 Message-Id: <20210319062752.145730-19-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Apply the SerIRQ ID and level/sense behaviours from the devicetree if provided. Signed-off-by: Andrew Jeffery --- drivers/char/ipmi/kcs_bmc_aspeed.c | 179 ++++++++++++++++++++++++++++- 1 file changed, 177 insertions(+), 2 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 271845eb2e26..3782aef4eb73 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,22 @@ #define KCS_CHANNEL_MAX 4 +/* + * Field class descriptions + * + * LPCyE Enable LPC channel y + * IBFIEy Input Buffer Full IRQ Enable for LPC channel y + * IRQxEy Assert SerIRQ x for LPC channel y (Deprecated, use IDyIRQX, IRQXEy) + * IDyIRQX Use the specified 4-bit SerIRQ for LPC channel y + * SELyIRQX SerIRQ polarity for LPC channel y (low: 0, high: 1) + * IRQXEy Assert the SerIRQ specified in IDyIRQX for LPC channel y + */ + +#define LPC_TYIRQX_LOW 0b00 +#define LPC_TYIRQX_HIGH 0b01 +#define LPC_TYIRQX_RSVD 0b10 +#define LPC_TYIRQX_RISING 0b11 + #define LPC_HICR0 0x000 #define LPC_HICR0_LPC3E BIT(7) #define LPC_HICR0_LPC2E BIT(6) @@ -39,6 +56,19 @@ #define LPC_HICR4 0x010 #define LPC_HICR4_LADR12AS BIT(7) #define LPC_HICR4_KCSENBL BIT(2) +#define LPC_SIRQCR0 0x070 +/* IRQ{12,1}E1 are deprecated as of AST2600 A3 but necessary for prior chips */ +#define LPC_SIRQCR0_IRQ12E1 BIT(1) +#define LPC_SIRQCR0_IRQ1E1 BIT(0) +#define LPC_HICR5 0x080 +#define LPC_HICR5_ID3IRQX_MASK GENMASK(23, 20) +#define LPC_HICR5_ID3IRQX_SHIFT 20 +#define LPC_HICR5_ID2IRQX_MASK GENMASK(19, 16) +#define LPC_HICR5_ID2IRQX_SHIFT 16 +#define LPC_HICR5_SEL3IRQX BIT(15) +#define LPC_HICR5_IRQXE3 BIT(14) +#define LPC_HICR5_SEL2IRQX BIT(13) +#define LPC_HICR5_IRQXE2 BIT(12) #define LPC_LADR3H 0x014 #define LPC_LADR3L 0x018 #define LPC_LADR12H 0x01C @@ -55,6 +85,13 @@ #define LPC_HICRB 0x100 #define LPC_HICRB_IBFIF4 BIT(1) #define LPC_HICRB_LPC4E BIT(0) +#define LPC_HICRC 0x104 +#define LPC_HICRC_ID4IRQX_MASK GENMASK(7, 4) +#define LPC_HICRC_ID4IRQX_SHIFT 4 +#define LPC_HICRC_TY4IRQX_MASK GENMASK(3, 2) +#define LPC_HICRC_TY4IRQX_SHIFT 2 +#define LPC_HICRC_OBF4_AUTO_CLR BIT(1) +#define LPC_HICRC_IRQXE4 BIT(0) #define LPC_LADR4 0x110 #define LPC_IDR4 0x114 #define LPC_ODR4 0x118 @@ -62,11 +99,21 @@ #define OBE_POLL_PERIOD (HZ / 2) +enum aspeed_kcs_irq_mode { + aspeed_kcs_irq_none, + aspeed_kcs_irq_serirq, +}; + struct aspeed_kcs_bmc { struct kcs_bmc_device kcs_bmc; struct regmap *map; + struct { + enum aspeed_kcs_irq_mode mode; + int id; + } upstream_irq; + struct { spinlock_t lock; bool remove; @@ -103,6 +150,49 @@ static void aspeed_kcs_outb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 data) rc = regmap_write(priv->map, reg, data); WARN(rc != 0, "regmap_write() failed: %d\n", rc); + + /* Trigger the upstream IRQ on ODR writes, if enabled */ + + switch (reg) { + case LPC_ODR1: + case LPC_ODR2: + case LPC_ODR3: + case LPC_ODR4: + break; + default: + return; + } + + if (priv->upstream_irq.mode != aspeed_kcs_irq_serirq) + return; + + switch (kcs_bmc->channel) { + case 1: + switch (priv->upstream_irq.id) { + case 12: + regmap_update_bits(priv->map, LPC_SIRQCR0, LPC_SIRQCR0_IRQ12E1, + LPC_SIRQCR0_IRQ12E1); + break; + case 1: + regmap_update_bits(priv->map, LPC_SIRQCR0, LPC_SIRQCR0_IRQ1E1, + LPC_SIRQCR0_IRQ1E1); + break; + default: + break; + } + break; + case 2: + regmap_update_bits(priv->map, LPC_HICR5, LPC_HICR5_IRQXE2, LPC_HICR5_IRQXE2); + break; + case 3: + regmap_update_bits(priv->map, LPC_HICR5, LPC_HICR5_IRQXE3, LPC_HICR5_IRQXE3); + break; + case 4: + regmap_update_bits(priv->map, LPC_HICRC, LPC_HICRC_IRQXE4, LPC_HICRC_IRQXE4); + break; + default: + break; + } } static void aspeed_kcs_updateb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 mask, u8 val) @@ -161,6 +251,73 @@ static void aspeed_kcs_set_address(struct kcs_bmc_device *kcs_bmc, u16 addr) } } +static inline int aspeed_kcs_map_serirq_type(u32 dt_type) +{ + switch (dt_type) { + case IRQ_TYPE_EDGE_RISING: + return LPC_TYIRQX_RISING; + case IRQ_TYPE_LEVEL_HIGH: + return LPC_TYIRQX_HIGH; + case IRQ_TYPE_LEVEL_LOW: + return LPC_TYIRQX_LOW; + default: + return -EINVAL; + } +} + +static int aspeed_kcs_config_upstream_irq(struct aspeed_kcs_bmc *priv, u32 id, u32 dt_type) +{ + unsigned int mask, val, hw_type; + + if (id > 15) + return -EINVAL; + + hw_type = aspeed_kcs_map_serirq_type(dt_type); + if (hw_type < 0) + return hw_type; + + priv->upstream_irq.mode = aspeed_kcs_irq_serirq; + priv->upstream_irq.id = id; + + switch (priv->kcs_bmc.channel) { + case 1: + /* Needs IRQxE1 rather than (ID1IRQX, SEL1IRQX, IRQXE1) before AST2600 A3 */ + break; + case 2: + if (!(hw_type == LPC_TYIRQX_LOW || hw_type == LPC_TYIRQX_HIGH)) + return -EINVAL; + + mask = LPC_HICR5_SEL2IRQX | LPC_HICR5_ID2IRQX_MASK; + val = (id << LPC_HICR5_ID2IRQX_SHIFT); + val |= (hw_type == LPC_TYIRQX_HIGH) ? LPC_HICR5_SEL2IRQX : 0; + regmap_update_bits(priv->map, LPC_HICR5, mask, val); + + break; + case 3: + if (!(hw_type == LPC_TYIRQX_LOW || hw_type == LPC_TYIRQX_HIGH)) + return -EINVAL; + + mask = LPC_HICR5_SEL3IRQX | LPC_HICR5_ID3IRQX_MASK; + val = (id << LPC_HICR5_ID3IRQX_SHIFT); + val |= (hw_type == LPC_TYIRQX_HIGH) ? LPC_HICR5_SEL3IRQX : 0; + regmap_update_bits(priv->map, LPC_HICR5, mask, val); + + break; + case 4: + mask = LPC_HICRC_ID4IRQX_MASK | LPC_HICRC_TY4IRQX_MASK | LPC_HICRC_OBF4_AUTO_CLR; + val = (id << LPC_HICRC_ID4IRQX_SHIFT) | (hw_type << LPC_HICRC_TY4IRQX_SHIFT); + regmap_update_bits(priv->map, LPC_HICRC, mask, val); + break; + default: + dev_warn(priv->kcs_bmc.dev, + "SerIRQ configuration not supported on KCS channel %d\n", + priv->kcs_bmc.channel); + return -EINVAL; + } + + return 0; +} + static void aspeed_kcs_enable_channel(struct kcs_bmc_device *kcs_bmc, bool enable) { struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); @@ -267,7 +424,7 @@ static irqreturn_t aspeed_kcs_irq(int irq, void *arg) return rc == KCS_BMC_EVENT_HANDLED ? IRQ_HANDLED : IRQ_NONE; } -static int aspeed_kcs_config_irq(struct kcs_bmc_device *kcs_bmc, +static int aspeed_kcs_config_downstream_irq(struct kcs_bmc_device *kcs_bmc, struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -371,6 +528,8 @@ static int aspeed_kcs_probe(struct platform_device *pdev) struct aspeed_kcs_bmc *priv; struct device_node *np; int rc, channel, addr; + bool have_upstream_irq; + u32 upstream_irq[2]; np = pdev->dev.of_node->parent; if (!of_device_is_compatible(np, "aspeed,ast2400-lpc-v2") && @@ -379,6 +538,7 @@ static int aspeed_kcs_probe(struct platform_device *pdev) dev_err(&pdev->dev, "unsupported LPC device binding\n"); return -ENODEV; } + ops = of_device_get_match_data(&pdev->dev); if (!ops) return -EINVAL; @@ -391,6 +551,13 @@ static int aspeed_kcs_probe(struct platform_device *pdev) if (addr < 0) return addr; + np = pdev->dev.of_node; + rc = of_property_read_u32_array(np, "aspeed,lpc-interrupts", upstream_irq, 2); + if ((rc && rc != -EINVAL)) + return -EINVAL; + + have_upstream_irq = !rc; + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -413,10 +580,17 @@ static int aspeed_kcs_probe(struct platform_device *pdev) aspeed_kcs_set_address(kcs_bmc, addr); - rc = aspeed_kcs_config_irq(kcs_bmc, pdev); + /* Host to BMC IRQ */ + rc = aspeed_kcs_config_downstream_irq(kcs_bmc, pdev); if (rc) return rc; + /* BMC to Host IRQ */ + if (have_upstream_irq) + aspeed_kcs_config_upstream_irq(priv, upstream_irq[0], upstream_irq[1]); + else + priv->upstream_irq.mode = aspeed_kcs_irq_none; + platform_set_drvdata(pdev, priv); aspeed_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), 0); @@ -481,4 +655,5 @@ module_platform_driver(ast_kcs_bmc_driver); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Haiyue Wang "); +MODULE_AUTHOR("Andrew Jeffery "); MODULE_DESCRIPTION("Aspeed device interface to the KCS BMC device"); From patchwork Fri Mar 19 06:27:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455619 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=sJveB98k; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=TP7Ee5/k; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vDQ45Blz9sWP for ; Fri, 19 Mar 2021 17:31:18 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234091AbhCSGap (ORCPT ); Fri, 19 Mar 2021 02:30:45 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:40527 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234157AbhCSGaT (ORCPT ); Fri, 19 Mar 2021 02:30:19 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id 0103C580A7C; Fri, 19 Mar 2021 02:30:19 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:30:19 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=oezH8d9IZwsC6 Zot9Yj8OXXCheexp/7uKg5VoRs1yuA=; b=sJveB98kLtGHnIDcqCzg5OGrboV4I QOaVUYvRlnY3prqLVUiLO+2dbZ4Vd2i+euB2HLVzlyEO6BqQbIJmDRghzmInTXnv BikE9VczGoJ8KRNRnlK7Qvowm3uoVL3KDPYFEAHd6+JFWRruFFQGW7WBdceYUvA+ xwx5CGwGxEU8X3nHMealxGLtyI/LnTuVOiJxDyIVQRE1xE88FVcKc9ln+THsH2ll hpFDS1ATTPVIaNtrWczwJtQPmG6JlyZq8f+Pje4GJUzyHUGPskZcdU9ZXq4GHxgm Xbnb3jPDqcp6S+PHK6AZohYMnGsqnbQR9j9XEIW66rqKPhEHHBuEv1gMg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=oezH8d9IZwsC6Zot9Yj8OXXCheexp/7uKg5VoRs1yuA=; b=TP7Ee5/k 6akEI5Ra2r2ZM8aJc/WQelxqtmzblxHkl8eKKrumx/Qyd3S14Xu5ssLWhtYnLcI3 ZFEi/Xm6Qarn/mxmApSk5kznwItcYlM1JLptaho5o/S42XXQZ6fi66BG0SpDm/Fs 8ZR6Tm8eeZ8Q3pFE6gyMz+XwdTuMgvmAUzFQwD470AcUwoPXDP1Ua8x9Hfkw0fdv qUjhRuwrBg6LzvfWc9i/fV3+msgeJMQyxwRsnU9M5zzZuk2w9glYMxa0v7IPwXGm bF7GFNfSFhJrOl0xToDqju3XoArKAzmhOzFQfi8eehZ14nICZQbFtdLuhXT3EDrz FcyhsOvTRpLtbg== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppeduudekrddvuddtrddukedurdeh heenucevlhhushhtvghrufhiiigvpeeknecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnh gurhgvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 64A3C24005E; Fri, 19 Mar 2021 02:30:13 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, chiawei_wang@aspeedtech.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 20/21] ipmi: kcs_bmc_aspeed: Fix IBFIE typo from datasheet Date: Fri, 19 Mar 2021 16:57:51 +1030 Message-Id: <20210319062752.145730-20-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Input Buffer Full Interrupt Enable (IBFIE) is typoed as IBFIF for some registers in the datasheet. Fix the driver to use the sensible acronym. Signed-off-by: Andrew Jeffery Reviewed-by: Zev Weiss --- drivers/char/ipmi/kcs_bmc_aspeed.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 3782aef4eb73..7334b1f51dcc 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -50,9 +50,9 @@ #define LPC_HICR0_LPC2E BIT(6) #define LPC_HICR0_LPC1E BIT(5) #define LPC_HICR2 0x008 -#define LPC_HICR2_IBFIF3 BIT(3) -#define LPC_HICR2_IBFIF2 BIT(2) -#define LPC_HICR2_IBFIF1 BIT(1) +#define LPC_HICR2_IBFIE3 BIT(3) +#define LPC_HICR2_IBFIE2 BIT(2) +#define LPC_HICR2_IBFIE1 BIT(1) #define LPC_HICR4 0x010 #define LPC_HICR4_LADR12AS BIT(7) #define LPC_HICR4_KCSENBL BIT(2) @@ -83,7 +83,7 @@ #define LPC_STR2 0x040 #define LPC_STR3 0x044 #define LPC_HICRB 0x100 -#define LPC_HICRB_IBFIF4 BIT(1) +#define LPC_HICRB_IBFIE4 BIT(1) #define LPC_HICRB_LPC4E BIT(0) #define LPC_HICRC 0x104 #define LPC_HICRC_ID4IRQX_MASK GENMASK(7, 4) @@ -383,20 +383,20 @@ static void aspeed_kcs_irq_mask_update(struct kcs_bmc_device *kcs_bmc, u8 mask, switch (kcs_bmc->channel) { case 1: - regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIF1, - enable * LPC_HICR2_IBFIF1); + regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIE1, + enable * LPC_HICR2_IBFIE1); return; case 2: - regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIF2, - enable * LPC_HICR2_IBFIF2); + regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIE2, + enable * LPC_HICR2_IBFIE2); return; case 3: - regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIF3, - enable * LPC_HICR2_IBFIF3); + regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIE3, + enable * LPC_HICR2_IBFIE3); return; case 4: - regmap_update_bits(priv->map, LPC_HICRB, LPC_HICRB_IBFIF4, - enable * LPC_HICRB_IBFIF4); + regmap_update_bits(priv->map, LPC_HICRB, LPC_HICRB_IBFIE4, + enable * LPC_HICRB_IBFIE4); return; default: pr_warn("%s: Unsupported channel: %d", __func__, kcs_bmc->channel); From patchwork Fri Mar 19 06:27:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 1455620 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-gpio-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.a=rsa-sha256 header.s=fm2 header.b=G8nK0j7U; dkim=pass (2048-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.a=rsa-sha256 header.s=fm2 header.b=EXHv05Ur; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4F1vDR2TZcz9sW1 for ; Fri, 19 Mar 2021 17:31:19 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233986AbhCSGas (ORCPT ); Fri, 19 Mar 2021 02:30:48 -0400 Received: from new4-smtp.messagingengine.com ([66.111.4.230]:39585 "EHLO new4-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234186AbhCSGaZ (ORCPT ); Fri, 19 Mar 2021 02:30:25 -0400 Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailnew.nyi.internal (Postfix) with ESMTP id E73E9580A7D; Fri, 19 Mar 2021 02:30:24 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Fri, 19 Mar 2021 02:30:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm2; bh=LKmXDb+OBH8vc rQsLHQ/uqSreIyyMcXsaq0h99thI6g=; b=G8nK0j7Uqwpon5XvV7Npcqiz3GTWF uAzeceU/Xe8OQod1XLyx/1wZAOFmXZstWmzmPWKHj7AZVKBFh1XpEacubbbf4Nwp Wuu6JeP3vvWbibyUPh5dF0+YhErZSCmqjEloTdv1hN4mrmuEZQsVlBZitXqXIX3d /5A0gpa94j9IjFopZQo7jh0AIiPckvjIqqrMYA2UPVGOH38AcknNLHWeX0IVTKbh kWknSrqT72M/Rcll+J/BuQpDaZuhPLoilb9QoYvVs+8uMbrHTxcQZtZSMxFGgoOA tKczu4nPFzTSIcbUUhXWxMgIeELNy8IN0W8dYRXLru+FFYz1WjcTW0LkA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm2; bh=LKmXDb+OBH8vcrQsLHQ/uqSreIyyMcXsaq0h99thI6g=; b=EXHv05Ur MamlBSitCbHu1FVmgDkgath0o0S7qIHesS4QPcVr1Zj7LC5hu4xKlicy6mUVgKsg Xq8qEW1b0XwGbxKAvY0XIsU3uWvdXaZBnu54QMhSG7Co8xczxo0eAkBR9wY9PN1M NzgcgrF1xAfr/lo3hup0zci4pQroWcoWM92sFzptRHW3HQdnsFfJGUYm0JZ0J9+x 99sh0qyN8Fm2W7Yf2UjwySdhWttumOsxWJfr/YNhQR2StMikhE8QNm9+x8M/guRa EStr05v3LdBQ0i5LPu40X/xnQimciaJpPd1cP6Swjc9zQg7aijXwNDy5X0ektT7x M0+c+KCGpDiFww== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduledrudefjedgleeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehnughrvgifucflvghffhgvrhihuceorghnughrvgifsegr jhdrihgurdgruheqnecuggftrfgrthhtvghrnhepjefgvdevheetkeevgeegleelgfelte etjeffleffvdduudevieffgeetleevhfetnecukfhppeduudekrddvuddtrddukedurdeh heenucevlhhushhtvghrufhiiigvpeelnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrnh gurhgvfiesrghjrdhiugdrrghu X-ME-Proxy: Received: from localhost.localdomain (ppp118-210-181-55.adl-adc-lon-bras34.tpg.internode.on.net [118.210.181.55]) by mail.messagingengine.com (Postfix) with ESMTPA id 5A119240057; Fri, 19 Mar 2021 02:30:19 -0400 (EDT) From: Andrew Jeffery To: openipmi-developer@lists.sourceforge.net, openbmc@lists.ozlabs.org, minyard@acm.org Cc: joel@jms.id.au, ryan_chen@aspeedtech.com, devicetree@vger.kernel.org, tmaimon77@gmail.com, linux-aspeed@lists.ozlabs.org, linux-gpio@vger.kernel.org, avifishman70@gmail.com, venture@google.com, linus.walleij@linaro.org, linux-kernel@vger.kernel.org, tali.perry1@gmail.com, robh+dt@kernel.org, lee.jones@linaro.org, chiawei_wang@aspeedtech.com, linux-arm-kernel@lists.infradead.org, benjaminfair@google.com Subject: [PATCH v2 21/21] ipmi: kcs_bmc_aspeed: Optionally apply status address Date: Fri, 19 Mar 2021 16:57:52 +1030 Message-Id: <20210319062752.145730-21-andrew@aj.id.au> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210319062752.145730-1-andrew@aj.id.au> References: <20210319062752.145730-1-andrew@aj.id.au> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Some Aspeed KCS devices can derive the status register address from the address of the data register. As such, the address of the status register can be implicit in the configuration if desired. On the other hand, sometimes address schemes might be requested that are incompatible with the default addressing scheme. Allow these requests where possible if the devicetree specifies the status register address. Signed-off-by: Andrew Jeffery Reviewed-by: Chia-Wei Wang --- drivers/char/ipmi/kcs_bmc_aspeed.c | 113 +++++++++++++++++++++-------- 1 file changed, 81 insertions(+), 32 deletions(-) diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c index 7334b1f51dcc..98789b837690 100644 --- a/drivers/char/ipmi/kcs_bmc_aspeed.c +++ b/drivers/char/ipmi/kcs_bmc_aspeed.c @@ -83,6 +83,8 @@ #define LPC_STR2 0x040 #define LPC_STR3 0x044 #define LPC_HICRB 0x100 +#define LPC_HICRB_EN16LADR2 BIT(5) +#define LPC_HICRB_EN16LADR1 BIT(4) #define LPC_HICRB_IBFIE4 BIT(1) #define LPC_HICRB_LPC4E BIT(0) #define LPC_HICRC 0x104 @@ -96,6 +98,11 @@ #define LPC_IDR4 0x114 #define LPC_ODR4 0x118 #define LPC_STR4 0x11C +#define LPC_LSADR12 0x120 +#define LPC_LSADR12_LSADR2_MASK GENMASK(31, 16) +#define LPC_LSADR12_LSADR2_SHIFT 16 +#define LPC_LSADR12_LSADR1_MASK GENMASK(15, 0) +#define LPC_LSADR12_LSADR1_SHIFT 0 #define OBE_POLL_PERIOD (HZ / 2) @@ -123,7 +130,7 @@ struct aspeed_kcs_bmc { struct aspeed_kcs_of_ops { int (*get_channel)(struct platform_device *pdev); - int (*get_io_address)(struct platform_device *pdev); + int (*get_io_address)(struct platform_device *pdev, u32 addrs[2]); }; static inline struct aspeed_kcs_bmc *to_aspeed_kcs_bmc(struct kcs_bmc_device *kcs_bmc) @@ -217,38 +224,64 @@ static void aspeed_kcs_updateb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 mask, * C. KCS4 * D / C : CA4h / CA5h */ -static void aspeed_kcs_set_address(struct kcs_bmc_device *kcs_bmc, u16 addr) +static int aspeed_kcs_set_address(struct kcs_bmc_device *kcs_bmc, u32 addrs[2], int nr_addrs) { struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); - switch (kcs_bmc->channel) { + if (WARN_ON(nr_addrs < 1 || nr_addrs > 2)) + return -EINVAL; + + switch (priv->kcs_bmc.channel) { case 1: - regmap_update_bits(priv->map, LPC_HICR4, - LPC_HICR4_LADR12AS, 0); - regmap_write(priv->map, LPC_LADR12H, addr >> 8); - regmap_write(priv->map, LPC_LADR12L, addr & 0xFF); + regmap_update_bits(priv->map, LPC_HICR4, LPC_HICR4_LADR12AS, 0); + regmap_write(priv->map, LPC_LADR12H, addrs[0] >> 8); + regmap_write(priv->map, LPC_LADR12L, addrs[0] & 0xFF); + if (nr_addrs == 2) { + regmap_update_bits(priv->map, LPC_LSADR12, LPC_LSADR12_LSADR1_MASK, + addrs[1] << LPC_LSADR12_LSADR1_SHIFT); + + regmap_update_bits(priv->map, LPC_HICRB, LPC_HICRB_EN16LADR1, + LPC_HICRB_EN16LADR1); + } break; case 2: - regmap_update_bits(priv->map, LPC_HICR4, - LPC_HICR4_LADR12AS, LPC_HICR4_LADR12AS); - regmap_write(priv->map, LPC_LADR12H, addr >> 8); - regmap_write(priv->map, LPC_LADR12L, addr & 0xFF); + regmap_update_bits(priv->map, LPC_HICR4, LPC_HICR4_LADR12AS, LPC_HICR4_LADR12AS); + regmap_write(priv->map, LPC_LADR12H, addrs[0] >> 8); + regmap_write(priv->map, LPC_LADR12L, addrs[0] & 0xFF); + if (nr_addrs == 2) { + regmap_update_bits(priv->map, LPC_LSADR12, LPC_LSADR12_LSADR2_MASK, + addrs[1] << LPC_LSADR12_LSADR2_SHIFT); + + regmap_update_bits(priv->map, LPC_HICRB, LPC_HICRB_EN16LADR2, + LPC_HICRB_EN16LADR2); + } break; case 3: - regmap_write(priv->map, LPC_LADR3H, addr >> 8); - regmap_write(priv->map, LPC_LADR3L, addr & 0xFF); + if (nr_addrs == 2) { + dev_err(priv->kcs_bmc.dev, + "Channel 3 only supports inferred status IO address\n"); + return -EINVAL; + } + + regmap_write(priv->map, LPC_LADR3H, addrs[0] >> 8); + regmap_write(priv->map, LPC_LADR3L, addrs[0] & 0xFF); break; case 4: - regmap_write(priv->map, LPC_LADR4, ((addr + 1) << 16) | - addr); + if (nr_addrs == 1) + regmap_write(priv->map, LPC_LADR4, ((addrs[0] + 1) << 16) | addrs[0]); + else + regmap_write(priv->map, LPC_LADR4, (addrs[1] << 16) | addrs[0]); + break; default: - break; + return -EINVAL; } + + return 0; } static inline int aspeed_kcs_map_serirq_type(u32 dt_type) @@ -462,18 +495,18 @@ static int aspeed_kcs_of_v1_get_channel(struct platform_device *pdev) return channel; } -static int aspeed_kcs_of_v1_get_io_address(struct platform_device *pdev) +static int +aspeed_kcs_of_v1_get_io_address(struct platform_device *pdev, u32 addrs[2]) { - u32 slave; int rc; - rc = of_property_read_u32(pdev->dev.of_node, "kcs_addr", &slave); - if (rc || slave > 0xffff) { + rc = of_property_read_u32(pdev->dev.of_node, "kcs_addr", addrs); + if (rc || addrs[0] > 0xffff) { dev_err(&pdev->dev, "no valid 'kcs_addr' configured\n"); return -EINVAL; } - return slave; + return 1; } static int aspeed_kcs_of_v2_get_channel(struct platform_device *pdev) @@ -509,16 +542,27 @@ static int aspeed_kcs_of_v2_get_channel(struct platform_device *pdev) return -EINVAL; } -static int aspeed_kcs_of_v2_get_io_address(struct platform_device *pdev) +static int +aspeed_kcs_of_v2_get_io_address(struct platform_device *pdev, u32 addrs[2]) { - uint32_t slave; int rc; - rc = of_property_read_u32(pdev->dev.of_node, "aspeed,lpc-io-reg", &slave); - if (rc || slave > 0xffff) + rc = of_property_read_variable_u32_array(pdev->dev.of_node, + "aspeed,lpc-io-reg", + addrs, 1, 2); + if (rc < 0) + return rc; + + if (WARN_ON(rc == 0)) + return -EINVAL; + + if (addrs[0] > 0xffff) + return -EINVAL; + + if (rc == 2 && addrs[1] > 0xffff) return -EINVAL; - return slave; + return rc; } static int aspeed_kcs_probe(struct platform_device *pdev) @@ -527,9 +571,11 @@ static int aspeed_kcs_probe(struct platform_device *pdev) struct kcs_bmc_device *kcs_bmc; struct aspeed_kcs_bmc *priv; struct device_node *np; - int rc, channel, addr; bool have_upstream_irq; u32 upstream_irq[2]; + int rc, channel; + int nr_addrs; + u32 addrs[2]; np = pdev->dev.of_node->parent; if (!of_device_is_compatible(np, "aspeed,ast2400-lpc-v2") && @@ -547,9 +593,9 @@ static int aspeed_kcs_probe(struct platform_device *pdev) if (channel < 0) return channel; - addr = ops->get_io_address(pdev); - if (addr < 0) - return addr; + nr_addrs = ops->get_io_address(pdev, addrs); + if (nr_addrs < 0) + return nr_addrs; np = pdev->dev.of_node; rc = of_property_read_u32_array(np, "aspeed,lpc-interrupts", upstream_irq, 2); @@ -578,7 +624,9 @@ static int aspeed_kcs_probe(struct platform_device *pdev) priv->obe.remove = false; timer_setup(&priv->obe.timer, aspeed_kcs_check_obe, 0); - aspeed_kcs_set_address(kcs_bmc, addr); + rc = aspeed_kcs_set_address(kcs_bmc, addrs, nr_addrs); + if (rc) + return rc; /* Host to BMC IRQ */ rc = aspeed_kcs_config_downstream_irq(kcs_bmc, pdev); @@ -600,7 +648,8 @@ static int aspeed_kcs_probe(struct platform_device *pdev) if (rc < 0) return rc; - dev_info(&pdev->dev, "Initialised channel %d at 0x%x\n", kcs_bmc->channel, addr); + dev_info(&pdev->dev, "Initialised channel %d at 0x%x\n", + kcs_bmc->channel, addrs[0]); return 0; }