From patchwork Wed Sep 30 01:40:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luka Kovacic X-Patchwork-Id: 11807543 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 95990139F for ; Wed, 30 Sep 2020 01:41:44 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5872C2145D for ; Wed, 30 Sep 2020 01:41:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="vuXOZeGp"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=sartura-hr.20150623.gappssmtp.com header.i=@sartura-hr.20150623.gappssmtp.com header.b="Uoc8UZeN" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5872C2145D Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=sartura.hr Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=8NpnAg4ph5LuuiWBMHru6ypuTbjBQoEUgvPWyCVCplM=; b=vuXOZeGpVYAnkQhuzrEbFw0PN Wa7SfQYAPFw2nqDsuyPU2pisFmu9JM0i32FeHmLZabiaBRMGyQLEivoUVHKVyVBG+ujcsuuWcNHtM GjxiOhFNJCD2Z9YaKwZcjYqIWy4D0inUTRf7v/h5X2zXsG87C11TBlLLgSRFBISYWONGlMBuMgMmk JpAcOG1sAY1L5O2Pa0bzZuEk33dfQfh6FLwDaOrbPbIVpBmM80lEVkQHgbbQD8HI1IegXHb9JBRA6 QiDHTPz51Z1TPCyi1EQOwf5XgTzM++TDrrXbiUxJH2se0wKMAYvRlfQiUDy5jXoXNvyBFO12jZZ+Z kVEqGyFPg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kNR7b-0000Hh-8q; Wed, 30 Sep 2020 01:41:31 +0000 Received: from mail-ej1-x644.google.com ([2a00:1450:4864:20::644]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kNR7N-0000Cc-BE for linux-arm-kernel@lists.infradead.org; Wed, 30 Sep 2020 01:41:18 +0000 Received: by mail-ej1-x644.google.com with SMTP id o8so397949ejb.10 for ; Tue, 29 Sep 2020 18:41:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sartura-hr.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=aKXhASnbwI3DU5+uZfrFm6rdTWVPfT7vuUbIcV7FULg=; b=Uoc8UZeNK5M+s5nuovxLynHDX36scftzaeQHDH2+nc5SBnEtyxtEc7ycJD/ZMwqRnw vlawBaTzMLPeR+YkEGyhyNm+MvuiMTulDL1zT12BrzbMOVKuk/xeiAyQYLpzItlESwgw qKOqENbI9+eMp2czhA0rXPrBTXwQveOasQfEwStRI2lqG7ABOYyocUyKbZARFkY4CSj8 L05V9xfndM/oXVfRBM2rhh6FQGWWJd5rvqRpCRVRqRmilfKB6xFcRvL2C6YvVXkCT9JX J7G3UIqk+IDzJoaDkYzKPpHgQOYfhaSiss8aFkTZuTYGA7u8jo1x31rGeppfm6J+ivmg cDgA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=aKXhASnbwI3DU5+uZfrFm6rdTWVPfT7vuUbIcV7FULg=; b=QnugRyrJb0Der6c2CeH3X+mJ2xftRKrIECHxuBr6mPdnzZOJzwsnYHwRsH6wKEFSyz vlPRdj4X3ngQ3GlEebvwVOZ1in1Q98n0DUEcLNvdiv9bYkR4CfyC/kP1S1a0PQdCE74U dTpOzHZG3WbhWI8xWN+O9AJSrWcLh7l+EXxIiUl+eaCdmw/bYQwJ6CgpnE1KLcr56tcJ 0GjZvo9WAV52KGHRaBqTvgZAMdXFWPTV6N7Nl0m4FuL+xr+F9ukaqvl07YULPufNwCB0 lMXCKdztQOGh9Zdm3MNdrhqXbjHpUxCHu1QuyanW2/HQTYZNY+noogvw+Clbbbl/0NmA O1ZQ== X-Gm-Message-State: AOAM531zZKVnQo7U7FbhZZFWu1w8z7gXMw8tU8G0gHQrnjp4pH4pcGvA R5DCoB0rm9VFNsDxsC/pUFB+2Q== X-Google-Smtp-Source: ABdhPJyVisoZtpz1CPcJLHlAQaT6LZQvHdUwEaDtXADGg/E7qi+QTNvnce9jMQXQFRKKtYylhOKsZg== X-Received: by 2002:a17:906:86cd:: with SMTP id j13mr462643ejy.5.1601430074653; Tue, 29 Sep 2020 18:41:14 -0700 (PDT) Received: from localhost.localdomain ([2a00:ee2:4b0d:3000:290:faff:fe54:449c]) by smtp.gmail.com with ESMTPSA id q1sm203258ejy.37.2020.09.29.18.41.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Sep 2020 18:41:13 -0700 (PDT) From: Luka Kovacic To: linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-leds@vger.kernel.org Subject: [PATCH v3 1/7] dt-bindings: Add iEi vendor prefix and iEi WT61P803 PUZZLE driver bindings Date: Wed, 30 Sep 2020 03:40:52 +0200 Message-Id: <20200930014058.44460-2-luka.kovacic@sartura.hr> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200930014058.44460-1-luka.kovacic@sartura.hr> References: <20200930014058.44460-1-luka.kovacic@sartura.hr> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200929_214117_409360_AD4DFD69 X-CRM114-Status: GOOD ( 19.34 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:644 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: andrew@lunn.ch, jdelvare@suse.com, luka.perkov@sartura.hr, jason@lakedaemon.net, gregory.clement@bootlin.com, marek.behun@nic.cz, Luka Kovacic , robh+dt@kernel.org, dmurphy@ti.com, pavel@ucw.cz, robert.marko@sartura.hr, lee.jones@linaro.org, linux@roeck-us.net Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Add the iEi WT61P803 PUZZLE Device Tree bindings for MFD, HWMON and LED drivers. A new vendor prefix is also added accordingly for IEI Integration Corp. Signed-off-by: Luka Kovacic Cc: Luka Perkov Cc: Robert Marko --- .../hwmon/iei,wt61p803-puzzle-hwmon.yaml | 41 ++++++++++ .../leds/iei,wt61p803-puzzle-leds.yaml | 45 ++++++++++ .../bindings/mfd/iei,wt61p803-puzzle.yaml | 82 +++++++++++++++++++ .../devicetree/bindings/vendor-prefixes.yaml | 2 + 4 files changed, 170 insertions(+) create mode 100644 Documentation/devicetree/bindings/hwmon/iei,wt61p803-puzzle-hwmon.yaml create mode 100644 Documentation/devicetree/bindings/leds/iei,wt61p803-puzzle-leds.yaml create mode 100644 Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml diff --git a/Documentation/devicetree/bindings/hwmon/iei,wt61p803-puzzle-hwmon.yaml b/Documentation/devicetree/bindings/hwmon/iei,wt61p803-puzzle-hwmon.yaml new file mode 100644 index 000000000000..37f0030df237 --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/iei,wt61p803-puzzle-hwmon.yaml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/hwmon/iei,wt61p803-puzzle-hwmon.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: iEi WT61P803 PUZZLE MCU HWMON module from IEI Integration Corp. + +maintainers: + - Luka Kovacic + +description: | + This module is a part of the iEi WT61P803 PUZZLE MFD device. For more details + see Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml. + + The HWMON module is a sub-node of the MCU node in the Device Tree. + +properties: + compatible: + const: iei,wt61p803-puzzle-hwmon + +patternProperties: + "^fan-group@[0-1]$": + type: object + properties: + reg: + minimum: 0 + maximum: 1 + description: + Fan group ID + cooling-levels: + maxItems: 255 + description: + Cooling levels for the fans (PWM value mapping) + description: | + Properties for each fan group. + required: + - reg + +required: + - compatible diff --git a/Documentation/devicetree/bindings/leds/iei,wt61p803-puzzle-leds.yaml b/Documentation/devicetree/bindings/leds/iei,wt61p803-puzzle-leds.yaml new file mode 100644 index 000000000000..0d353e5803bf --- /dev/null +++ b/Documentation/devicetree/bindings/leds/iei,wt61p803-puzzle-leds.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/iei,wt61p803-puzzle-leds.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: iEi WT61P803 PUZZLE MCU LED module from IEI Integration Corp. + +maintainers: + - Luka Kovacic + +description: | + This module is a part of the iEi WT61P803 PUZZLE MFD device. For more details + see Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml. + + The LED module is a sub-node of the MCU node in the Device Tree. + +properties: + compatible: + const: iei,wt61p803-puzzle-leds + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + +patternProperties: + "^led@0$": + type: object + $ref: common.yaml + description: | + Properties for a single LED. + + properties: + reg: + description: + Index of the LED. Only one LED is supported at the moment. + minimum: 0 + maximum: 0 + +required: + - compatible + - "#address-cells" + - "#size-cells" diff --git a/Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml b/Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml new file mode 100644 index 000000000000..79a232d75093 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/iei,wt61p803-puzzle.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: iEi WT61P803 PUZZLE MCU from IEI Integration Corp. + +maintainers: + - Luka Kovacic + +description: | + iEi WT61P803 PUZZLE MCU is embedded in some iEi Puzzle series boards. + It's used for controlling system power states, fans, LEDs and temperature + sensors. + + For Device Tree bindings of other sub-modules (HWMON, LEDs) refer to the + binding documents under the respective subsystem directories. + +properties: + compatible: + const: iei,wt61p803-puzzle + + current-speed: + description: + Serial bus speed in bps + maxItems: 1 + + enable-beep: true + + iei-wt61p803-hwmon: + $ref: ../hwmon/iei,wt61p803-puzzle-hwmon.yaml + + leds: + $ref: ../leds/iei,wt61p803-puzzle-leds.yaml + +required: + - compatible + - current-speed + +examples: + - | + #include + serial { + status = "okay"; + mcu { + compatible = "iei,wt61p803-puzzle"; + current-speed = <115200>; + enable-beep; + + leds { + compatible = "iei,wt61p803-puzzle-leds"; + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + function = LED_FUNCTION_POWER; + color = ; + }; + }; + + iei-wt61p803-puzzle-hwmon { + compatible = "iei,wt61p803-puzzle-hwmon"; + + #address-cells = <1>; + #size-cells = <0>; + + fan-group@0 { + #cooling-cells = <2>; + reg = <0x00>; + cooling-levels = <64 102 170 230 250>; + }; + + fan-group@1 { + #cooling-cells = <2>; + reg = <0x01>; + cooling-levels = <64 102 170 230 250>; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 63996ab03521..5f2595f0b2ad 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -467,6 +467,8 @@ patternProperties: description: IC Plus Corp. "^idt,.*": description: Integrated Device Technologies, Inc. + "^iei,.*": + description: IEI Integration Corp. "^ifi,.*": description: Ingenieurburo Fur Ic-Technologie (I/F/I) "^ilitek,.*": From patchwork Wed Sep 30 01:40:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luka Kovacic X-Patchwork-Id: 11807555 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 77C516CB for ; Wed, 30 Sep 2020 01:43:22 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1D53F20738 for ; Wed, 30 Sep 2020 01:43:22 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="boq2/Ur7"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=sartura-hr.20150623.gappssmtp.com header.i=@sartura-hr.20150623.gappssmtp.com header.b="bq5DM17P" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1D53F20738 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=sartura.hr Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=5KsCnNd6QmZ86YEuLw2VNK5hmjOMk+ZBV0mVg/57V0A=; b=boq2/Ur77r8o6vvM6T2+S+tHF +Qno5019ghLNQG3dkuZ27aycPeOHkpFZiScLNCzvxqm6386ZZcw5pafn0j/Wx3y+NN8TcJTOuiuUa JNG2MrbodDdusJsqOvdtdwr+U88Du7VeJ6bPvCwKdTJRKHKEC4mCV0G6pS5xOjc2z4LuREiLhNzk6 LEkaQObMIf3K9tbIAa+ElV+d6TSwGurfV3AwCgxyQ3aEx6ROCdlMAXg9Z8n6EpnD955mym8jjA41C B5LrCT1vI8BbtjzABBWiZpRjmO+3jgmTQqBC6luRIaXPoHMoCTWyb23vxbA3B/SoTnub29AGUI6P/ gNAxcHdRw==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kNR7f-0000IP-33; Wed, 30 Sep 2020 01:41:35 +0000 Received: from mail-ej1-x642.google.com ([2a00:1450:4864:20::642]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kNR7N-0000Cu-Tz for linux-arm-kernel@lists.infradead.org; Wed, 30 Sep 2020 01:41:22 +0000 Received: by mail-ej1-x642.google.com with SMTP id u21so450610eja.2 for ; Tue, 29 Sep 2020 18:41:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sartura-hr.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=cs+tXdMsDSuPelBXo383gL0c/DfXbE96Sc0THLc6wfY=; b=bq5DM17PHZ1nFZDn1IUZIMzj2bW/eP2Lq0/JDDQMnlsVHwRqQ6UA4YHhPEvKYU0Te9 eCg6w4q7MFh577Qqmhco2d2HI4zYygcl2wlG0gB7IdNJtYFC9iioNELP79/duv+pDccK xqw/9Xy3Mygb3QJdscUojNL8+6bNqGXcQmDbCc1xRe0lfEosdtxAFrMy9h+jSVefdb4v 4AArc0QTnWcbsJUZ2R5/ElFIsmk97MBl6/73ovzwhDikElgQeJ6sa38pq7aaMEMn+H/W aWw0Q/n0OiWjR7HOYA8KUpXDto+CEWMo95vXPzmNlT76lMgooASWEep+tATCA5p8teZJ t4ng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=cs+tXdMsDSuPelBXo383gL0c/DfXbE96Sc0THLc6wfY=; b=FjLWshFA2CCUy/BF6q0jCsUTpN/FHPz6BuDBNsQv/ieRPtAva69+AJwIJRKC7oLyrI 5M3P/JkuDhdrOeLUUSXx8ye5rSlU8ls8WjLBqio2Zc9pCQpPwrEb7kefX9Vk9TFsTffM ATYTIbEQrP2aEHNK7XSW99BAOqlD8eXIrUBANRlMnqahByoOVu1h1Uc+WLJC+LYKiUJI 97969ghS5niEA3LKHPwLzEGJYsS7X3f2CDfwdsqvJfUqaVyReqSfl2koAUKc/xE+RONY QFKhIu9PNywgiFjXn4mKYHCm04jDxG9ZZbqXC31tC9t1AlIy8uA2DlcDOeGL03uLVFa5 kqwg== X-Gm-Message-State: AOAM532uD4Wuavf9jQkEAsjL6E8iSgDjMvN+4+teG+rYItyd87WnlHgi cNYQYb9QyXz4CUAenv2a9plRxQ== X-Google-Smtp-Source: ABdhPJwZrmpMTKi80N5a3KBIk02ZKlCgDX05lxKdxlqrqtLrJT2LbS0KgaOSTK3Xo/NuHTRGqDV36A== X-Received: by 2002:a17:906:e05:: with SMTP id l5mr473661eji.173.1601430076463; Tue, 29 Sep 2020 18:41:16 -0700 (PDT) Received: from localhost.localdomain ([2a00:ee2:4b0d:3000:290:faff:fe54:449c]) by smtp.gmail.com with ESMTPSA id q1sm203258ejy.37.2020.09.29.18.41.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Sep 2020 18:41:15 -0700 (PDT) From: Luka Kovacic To: linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-leds@vger.kernel.org Subject: [PATCH v3 2/7] drivers: mfd: Add a driver for iEi WT61P803 PUZZLE MCU Date: Wed, 30 Sep 2020 03:40:53 +0200 Message-Id: <20200930014058.44460-3-luka.kovacic@sartura.hr> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200930014058.44460-1-luka.kovacic@sartura.hr> References: <20200930014058.44460-1-luka.kovacic@sartura.hr> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200929_214118_177608_BD0F2B73 X-CRM114-Status: GOOD ( 31.31 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:642 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: andrew@lunn.ch, jdelvare@suse.com, luka.perkov@sartura.hr, jason@lakedaemon.net, gregory.clement@bootlin.com, marek.behun@nic.cz, Luka Kovacic , robh+dt@kernel.org, dmurphy@ti.com, pavel@ucw.cz, robert.marko@sartura.hr, lee.jones@linaro.org, linux@roeck-us.net Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Add a driver for the iEi WT61P803 PUZZLE microcontroller, used in some iEi Puzzle series devices. The microcontroller controls system power, temperature sensors, fans and LEDs. This driver implements the core functionality for device communication over the system serial (serdev bus). It handles MCU messages and the internal MCU properties. Some properties can be managed over sysfs. Signed-off-by: Luka Kovacic Cc: Luka Perkov Cc: Robert Marko Reported-by: kernel test robot --- drivers/mfd/Kconfig | 8 + drivers/mfd/Makefile | 1 + drivers/mfd/iei-wt61p803-puzzle.c | 1045 +++++++++++++++++++++++ include/linux/mfd/iei-wt61p803-puzzle.h | 69 ++ 4 files changed, 1123 insertions(+) create mode 100644 drivers/mfd/iei-wt61p803-puzzle.c create mode 100644 include/linux/mfd/iei-wt61p803-puzzle.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 33df0837ab41..b1588845894e 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -2118,5 +2118,13 @@ config SGI_MFD_IOC3 If you have an SGI Origin, Octane, or a PCI IOC3 card, then say Y. Otherwise say N. +config MFD_IEI_WT61P803_PUZZLE + tristate "iEi WT61P803 PUZZLE MCU driver" + depends on SERIAL_DEV_BUS + help + iEi WT61P803 PUZZLE is a system power management microcontroller + used for fan control, temperature sensor reading, LED control + and system identification. + endmenu endif diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index a60e5f835283..33b88023a68d 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -236,6 +236,7 @@ obj-$(CONFIG_MFD_HI655X_PMIC) += hi655x-pmic.o obj-$(CONFIG_MFD_DLN2) += dln2.o obj-$(CONFIG_MFD_RT5033) += rt5033.o obj-$(CONFIG_MFD_SKY81452) += sky81452.o +obj-$(CONFIG_MFD_IEI_WT61P803_PUZZLE) += iei-wt61p803-puzzle.o intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o diff --git a/drivers/mfd/iei-wt61p803-puzzle.c b/drivers/mfd/iei-wt61p803-puzzle.c new file mode 100644 index 000000000000..6c5f7588b936 --- /dev/null +++ b/drivers/mfd/iei-wt61p803-puzzle.c @@ -0,0 +1,1045 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* iEi WT61P803 PUZZLE MCU Driver + * System management microcontroller for fan control, temperature sensor reading, + * LED control and system identification on iEi Puzzle series ARM-based appliances. + * + * Copyright (C) 2020 Sartura Ltd. + * Author: Luka Kovacic + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IEI_WT61P803_PUZZLE_MAX_COMMAND_LENGTH (20 + 2) +#define IEI_WT61P803_PUZZLE_RESP_BUF_SIZE 512 + +#define IEI_WT61P803_PUZZLE_VERSION_MAC_LENGTH 17 +#define IEI_WT61P803_PUZZLE_VERSION_SN_LENGTH 36 +#define IEI_WT61P803_PUZZLE_VERSION_VERSION_LENGTH 6 +#define IEI_WT61P803_PUZZLE_VERSION_BUILD_INFO_LENGTH 16 +#define IEI_WT61P803_PUZZLE_VERSION_PROTOCOL_VERSION_LENGTH 8 + +/* Use HZ as a timeout value throughout the driver */ +#define IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT HZ + +/** + * struct iei_wt61p803_puzzle_mcu_status - MCU flags state + * + * @ac_recovery_status_flag: AC Recovery Status Flag + * @power_loss_recovery: System recovery after power loss + * @power_status: System Power-on Method + */ +struct iei_wt61p803_puzzle_mcu_status { + u8 ac_recovery_status_flag; + u8 power_loss_recovery; + u8 power_status; +}; + +/** + * enum iei_wt61p803_puzzle_reply_state - State of the reply + * @FRAME_OK: The frame was completely processed/received + * @FRAME_PROCESSING: First bytes were received, but the frame isn't complete + * @FRAME_STRUCT_EMPTY: The frame struct is empty, no data was received + * @FRAME_TIMEOUT: The frame processing timed out, communication failed + * + * Describes the general state of the frame that is currently being received. + */ +enum iei_wt61p803_puzzle_reply_state { + FRAME_OK = 0x00, + FRAME_PROCESSING = 0x01, + FRAME_STRUCT_EMPTY = 0xFF, + FRAME_TIMEOUT = 0xFE +}; + +/** + * struct iei_wt61p803_puzzle_reply - MCU reply + * + * @size: Size of the MCU reply + * @data: Full MCU reply buffer + * @state: Current state of the packet + * @received: Was the response fullfilled + */ +struct iei_wt61p803_puzzle_reply { + size_t size; + unsigned char *data; + u8 state; + struct completion received; +}; + +/** + * struct iei_wt61p803_puzzle_mcu_version - MCU version status + * + * @version: Primary firmware version + * @build_info: Build date and time + * @bootloader_mode: Status of the MCU operation + * @protocol_version: MCU communication protocol version + * @serial_number: Device factory serial number + * @mac_address: Device factory MAC addresses + */ +struct iei_wt61p803_puzzle_mcu_version { + char version[IEI_WT61P803_PUZZLE_VERSION_VERSION_LENGTH+1]; + char build_info[IEI_WT61P803_PUZZLE_VERSION_BUILD_INFO_LENGTH+1]; + bool bootloader_mode; + char protocol_version[IEI_WT61P803_PUZZLE_VERSION_PROTOCOL_VERSION_LENGTH+1]; + char serial_number[IEI_WT61P803_PUZZLE_VERSION_SN_LENGTH+1]; + char mac_address[8][IEI_WT61P803_PUZZLE_VERSION_MAC_LENGTH+1]; +}; + +/** + * struct iei_wt61p803_puzzle - iEi WT61P803 PUZZLE MCU Driver + * + * @serdev: Pointer to underlying serdev device + * @kobj: Pointer to kobject (sysfs) + * @reply_lock: Reply mutex lock + * @bus_lock: Bus mutex lock + * @reply: Pointer to the iei_wt61p803_puzzle_reply struct + * @version: MCU version related data + * @status: MCU status related data + * @response_buffer Command response buffer allocation + * @lock General member mutex lock + */ +struct iei_wt61p803_puzzle { + struct serdev_device *serdev; + struct kobject *kobj; + struct mutex reply_lock; + struct mutex bus_lock; + struct iei_wt61p803_puzzle_reply *reply; + struct iei_wt61p803_puzzle_mcu_version version; + struct iei_wt61p803_puzzle_mcu_status status; + unsigned char *response_buffer; + struct mutex lock; +}; + +static unsigned char iei_wt61p803_puzzle_checksum(unsigned char *buf, size_t len) +{ + unsigned char checksum = 0; + unsigned int i; + + for (i = 0; i < len; i++) + checksum ^= buf[i]; + + return checksum; +} + +static int iei_wt61p803_puzzle_process_resp(struct iei_wt61p803_puzzle *mcu, + unsigned char *raw_resp_data, size_t size) +{ + struct device *dev = &mcu->serdev->dev; + unsigned char checksum; + + mutex_lock(&mcu->reply_lock); + + /* Check the incoming frame header */ + if (!(raw_resp_data[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START || + raw_resp_data[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER || + (raw_resp_data[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM && + raw_resp_data[1] == IEI_WT61P803_PUZZLE_CMD_EEPROM_READ))) { + + /* Frame header is not correct, check whether to append */ + if (mcu->reply->state != FRAME_PROCESSING) { + dev_err(dev, "Invalid frame header and state (0x%x)", mcu->reply->state); + mutex_unlock(&mcu->reply_lock); + return -EIO; + } + + /* Append the frame to existing data */ + memcpy(mcu->reply->data+mcu->reply->size, raw_resp_data, size); + mcu->reply->size += size; + } else { + /* Start processing a new frame */ + memcpy(mcu->reply->data, raw_resp_data, size); + mcu->reply->size = size; + mcu->reply->state = FRAME_PROCESSING; + } + + checksum = iei_wt61p803_puzzle_checksum(mcu->reply->data, mcu->reply->size-1); + + if (checksum != mcu->reply->data[mcu->reply->size-1]) { + /* The checksum isn't matched yet, wait for new frames */ + mutex_unlock(&mcu->reply_lock); + return (int)size; + } + + /* Received all the data */ + mcu->reply->state = FRAME_OK; + complete(&mcu->reply->received); + + mutex_unlock(&mcu->reply_lock); + + return (int)size; +} + +static int iei_wt61p803_puzzle_recv_buf(struct serdev_device *serdev, + const unsigned char *data, size_t size) +{ + struct iei_wt61p803_puzzle *mcu = serdev_device_get_drvdata(serdev); + int ret; + + ret = iei_wt61p803_puzzle_process_resp(mcu, (unsigned char *)data, size); + + /* Return the number of processed bytes if function returns error */ + if (ret < 0) + return (int)size; + + return ret; +} + +static const struct serdev_device_ops iei_wt61p803_puzzle_serdev_device_ops = { + .receive_buf = iei_wt61p803_puzzle_recv_buf, + .write_wakeup = serdev_device_write_wakeup, +}; + +/** + * iei_wt61p803_puzzle_write_command_watchdog() - Watchdog of the normal cmd + * @mcu: Pointer to the iei_wt61p803_puzzle core MFD struct + * @cmd: Pointer to the char array to send (size should be content + 1 (xor)) + * @size: Size of the cmd char array + * @reply_data: Pointer to the reply/response data array (should be allocated) + * @reply_size: Pointer to size_t (size of reply_data) + * @retry_count: Number of times to retry sending the command to the MCU + */ +int iei_wt61p803_puzzle_write_command_watchdog(struct iei_wt61p803_puzzle *mcu, + unsigned char *cmd, size_t size, unsigned char *reply_data, + size_t *reply_size, int retry_count) +{ + struct device *dev = &mcu->serdev->dev; + int ret, i; + + for (i = 0; i < retry_count; i++) { + ret = iei_wt61p803_puzzle_write_command(mcu, cmd, size, + reply_data, reply_size); + + if (ret != -ETIMEDOUT) + return ret; + } + + dev_err(dev, "%s: Command response timed out. Retries: %d", __func__, retry_count); + + return -ETIMEDOUT; +} +EXPORT_SYMBOL_GPL(iei_wt61p803_puzzle_write_command_watchdog); + +/** + * iei_wt61p803_puzzle_write_command() - Send a structured command to the MCU + * @mcu: Pointer to the iei_wt61p803_puzzle core MFD struct + * @cmd: Pointer to the char array to send (size should be content + 1 (xor)) + * @size: Size of the cmd char array + * @reply_data: Pointer to the reply/response data array (should be allocated) + * + * Sends a structured command to the MCU. + */ +int iei_wt61p803_puzzle_write_command(struct iei_wt61p803_puzzle *mcu, + unsigned char *cmd, size_t size, unsigned char *reply_data, + size_t *reply_size) +{ + struct device *dev = &mcu->serdev->dev; + int ret; + int len = (int)size; + + if (size > IEI_WT61P803_PUZZLE_MAX_COMMAND_LENGTH) + return -EINVAL; + + cmd[len - 1] = iei_wt61p803_puzzle_checksum(cmd, size); + + mutex_lock(&mcu->bus_lock); + mutex_lock(&mcu->reply_lock); + + if (!mcu->reply) { + ret = -EFAULT; + goto exit; + } + + /* Initialize reply struct */ + reinit_completion(&mcu->reply->received); + mcu->reply->state = FRAME_STRUCT_EMPTY; + mcu->reply->size = 0; + mutex_unlock(&mcu->reply_lock); + + ret = serdev_device_write(mcu->serdev, cmd, len, IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT); + + if (ret < 0) { + mutex_unlock(&mcu->bus_lock); + return ret; + } + + if (!wait_for_completion_timeout(&mcu->reply->received, + IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT)) { + dev_err(dev, "Command reply receive timeout\n"); + mutex_lock(&mcu->reply_lock); + reinit_completion(&mcu->reply->received); + mcu->reply->state = FRAME_TIMEOUT; + + ret = -ETIMEDOUT; + goto exit; + } + + mutex_lock(&mcu->reply_lock); + + if (!mcu->reply) { + ret = -EFAULT; + goto exit; + } + + *reply_size = mcu->reply->size; + /* Copy the received data, as it will not be available after a new frame is received */ + memcpy(reply_data, mcu->reply->data, mcu->reply->size); + + ret = 0; +exit: + mutex_unlock(&mcu->reply_lock); + mutex_unlock(&mcu->bus_lock); + return ret; +} +EXPORT_SYMBOL_GPL(iei_wt61p803_puzzle_write_command); + +int iei_wt61p803_puzzle_buzzer(struct iei_wt61p803_puzzle *mcu, bool long_beep) +{ + unsigned char buzzer_short_cmd[4] = { + IEI_WT61P803_PUZZLE_CMD_HEADER_START, + IEI_WT61P803_PUZZLE_CMD_FUNCTION_SINGLE, + '2' + }; /* Buzzer 0.5 sec */ + unsigned char buzzer_long_cmd[4] = { + IEI_WT61P803_PUZZLE_CMD_HEADER_START, + IEI_WT61P803_PUZZLE_CMD_FUNCTION_SINGLE, + '3' + }; /* Buzzer 1.5 sec */ + unsigned char *resp_buf = mcu->response_buffer; + size_t reply_size = 0; + int ret; + + mutex_lock(&mcu->lock); + ret = iei_wt61p803_puzzle_write_command(mcu, + long_beep ? buzzer_long_cmd : buzzer_short_cmd, 4, + resp_buf, &reply_size); + if (ret) + goto exit; + + if (reply_size != 3) { + ret = -EIO; + goto exit; + } + + if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && + resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && + resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) { + ret = -EPROTO; + goto exit; + } +exit: + mutex_unlock(&mcu->lock); + return ret; +} + +static int iei_wt61p803_puzzle_get_version(struct iei_wt61p803_puzzle *mcu) +{ + unsigned char version_cmd[3] = { + IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER, + IEI_WT61P803_PUZZLE_CMD_OTHER_VERSION + }; + unsigned char build_info_cmd[3] = { + IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER, + IEI_WT61P803_PUZZLE_CMD_OTHER_BUILD + }; + unsigned char bootloader_mode_cmd[3] = { + IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER, + IEI_WT61P803_PUZZLE_CMD_OTHER_BOOTLOADER_MODE + }; + unsigned char protocol_version_cmd[3] = { + IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER, + IEI_WT61P803_PUZZLE_CMD_OTHER_PROTOCOL_VERSION + }; + unsigned char *rb = mcu->response_buffer; + size_t reply_size = 0; + int ret; + + mutex_lock(&mcu->lock); + + ret = iei_wt61p803_puzzle_write_command(mcu, version_cmd, + sizeof(version_cmd), rb, &reply_size); + if (ret) + goto err; + if (reply_size < 7) { + ret = -EIO; + goto err; + } + sprintf(mcu->version.version, "v%c.%c%c%c", rb[2], rb[3], rb[4], rb[5]); + + ret = iei_wt61p803_puzzle_write_command(mcu, build_info_cmd, + sizeof(build_info_cmd), rb, &reply_size); + if (ret) + goto err; + if (reply_size < 15) { + ret = -EIO; + goto err; + } + sprintf(mcu->version.build_info, "%c%c/%c%c/%c%c%c%c %c%c:%c%c", + rb[8], rb[9], rb[6], rb[7], rb[2], + rb[3], rb[4], rb[5], rb[10], rb[11], + rb[12], rb[13]); + + ret = iei_wt61p803_puzzle_write_command(mcu, bootloader_mode_cmd, + sizeof(bootloader_mode_cmd), rb, &reply_size); + if (ret) + goto err; + if (reply_size < 4) { + ret = -EIO; + goto err; + } + if (rb[2] == IEI_WT61P803_PUZZLE_CMD_OTHER_MODE_APPS) + mcu->version.bootloader_mode = false; + else if (rb[2] == IEI_WT61P803_PUZZLE_CMD_OTHER_MODE_BOOTLOADER) + mcu->version.bootloader_mode = true; + + ret = iei_wt61p803_puzzle_write_command(mcu, protocol_version_cmd, + sizeof(protocol_version_cmd), rb, &reply_size); + if (ret) + goto err; + if (reply_size < 9) { + ret = -EIO; + goto err; + } + sprintf(mcu->version.protocol_version, "v%c.%c%c%c%c%c", + rb[7], rb[6], rb[5], rb[4], rb[3], rb[2]); +err: + mutex_unlock(&mcu->lock); + return ret; +} + +static int iei_wt61p803_puzzle_get_mcu_status(struct iei_wt61p803_puzzle *mcu) +{ + unsigned char mcu_status_cmd[5] = { + IEI_WT61P803_PUZZLE_CMD_HEADER_START, + IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER, + IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS, + IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS + }; + unsigned char *resp_buf = mcu->response_buffer; + size_t reply_size = 0; + int ret; + + mutex_lock(&mcu->lock); + ret = iei_wt61p803_puzzle_write_command(mcu, mcu_status_cmd, + sizeof(mcu_status_cmd), resp_buf, &reply_size); + if (ret) + goto exit; + if (reply_size < 20) { + ret = -EIO; + goto exit; + } + + /* Response format: + * (IDX RESPONSE) + * 0 @ + * 1 O + * 2 S + * 3 S + * ... + * 5 AC Recovery Status Flag + * ... + * 10 Power Loss Recovery + * ... + * 19 Power Status (system power on method) + * 20 XOR checksum + */ + if (resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && + resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER && + resp_buf[2] == IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS && + resp_buf[3] == IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS) { + mcu->status.ac_recovery_status_flag = resp_buf[5]; + mcu->status.power_loss_recovery = resp_buf[10]; + mcu->status.power_status = resp_buf[19]; + } +exit: + mutex_unlock(&mcu->lock); + return ret; +} + +static int iei_wt61p803_puzzle_get_serial_number(struct iei_wt61p803_puzzle *mcu) +{ + unsigned char *resp_buf = mcu->response_buffer; + unsigned char serial_number_cmd[5] = { + IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM, + IEI_WT61P803_PUZZLE_CMD_EEPROM_READ, + 0x00, + 0x24 + }; + size_t reply_size = 0; + int ret; + + mutex_lock(&mcu->lock); + ret = iei_wt61p803_puzzle_write_command(mcu, serial_number_cmd, + sizeof(serial_number_cmd), resp_buf, &reply_size); + if (ret) + goto err; + + sprintf(mcu->version.serial_number, "%.*s", + IEI_WT61P803_PUZZLE_VERSION_SN_LENGTH, resp_buf + 4); +err: + mutex_unlock(&mcu->lock); + return ret; + +} + +static int iei_wt61p803_puzzle_write_serial_number(struct iei_wt61p803_puzzle *mcu, + unsigned char serial_number[36]) +{ + unsigned char *resp_buf = mcu->response_buffer; + unsigned char serial_number_header[4] = { + IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM, + IEI_WT61P803_PUZZLE_CMD_EEPROM_WRITE, + 0x00, + 0xC + }; + unsigned char serial_number_cmd[4+12+1]; /* header, serial number chunk, XOR checksum */ + size_t reply_size = 0; + int ret, sn_counter; + + /* The MCU can only handle 22 byte messages, send the S/N in chunks */ + mutex_lock(&mcu->lock); + for (sn_counter = 0; sn_counter < 3; sn_counter++) { + serial_number_header[2] = 0x0 + (0xC) * sn_counter; + + memcpy(serial_number_cmd, serial_number_header, 4); + memcpy(serial_number_cmd + 4, serial_number + (0xC) * sn_counter, 0xC); + + serial_number_cmd[sizeof(serial_number_cmd) - 1] = 0; + + ret = iei_wt61p803_puzzle_write_command(mcu, serial_number_cmd, + sizeof(serial_number_cmd), resp_buf, &reply_size); + if (ret) + goto err; + if (reply_size != 3) { + ret = -EIO; + goto err; + } + if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && + resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && + resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) { + ret = -EPROTO; + goto err; + } + } + + sprintf(mcu->version.serial_number, "%.*s", + IEI_WT61P803_PUZZLE_VERSION_SN_LENGTH, serial_number); +err: + mutex_unlock(&mcu->lock); + return ret; +} + +static int iei_wt61p803_puzzle_get_mac_addresses(struct iei_wt61p803_puzzle *mcu) +{ + unsigned char *resp_buf = mcu->response_buffer; + unsigned char mac_address_cmd[5] = { + IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM, + IEI_WT61P803_PUZZLE_CMD_EEPROM_READ, + 0x00, + 0x11 + }; + size_t reply_size = 0; + int ret, mac_counter; + + mutex_lock(&mcu->lock); + for (mac_counter = 0; mac_counter < 8; mac_counter++) { + mac_address_cmd[2] = 0x24 + (0x11) * mac_counter; + mac_address_cmd[4] = 0x00; + + ret = iei_wt61p803_puzzle_write_command(mcu, mac_address_cmd, + sizeof(mac_address_cmd), resp_buf, &reply_size); + if (ret) + continue; + + if (reply_size < 22) { + ret = -EIO; + goto err; + } + + sprintf(mcu->version.mac_address[mac_counter], "%.*s", + IEI_WT61P803_PUZZLE_VERSION_MAC_LENGTH, resp_buf + 4); + } +err: + mutex_unlock(&mcu->lock); + return ret; +} + +static int iei_wt61p803_puzzle_write_mac_address(struct iei_wt61p803_puzzle *mcu, + unsigned char mac_address[17], int mac_address_idx) +{ + unsigned char *resp_buf = mcu->response_buffer; + unsigned char mac_address_header[4] = { + IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM, + IEI_WT61P803_PUZZLE_CMD_EEPROM_WRITE, + 0x00, + 0x11 + }; + unsigned char mac_address_cmd[4+17+1]; /* header, MAC address, XOR checksum*/ + size_t reply_size = 0; + int ret; + + if (!(mac_address_idx < 8)) + return -EINVAL; + + mac_address_header[2] = 0x24 + (0x11) * mac_address_idx; + + /* Concat mac_address_header, mac_address to mac_address_cmd */ + memcpy(mac_address_cmd, mac_address_header, 4); + memcpy(mac_address_cmd + 4, mac_address, 17); + + mac_address_cmd[sizeof(mac_address_cmd) - 1] = 0; + + mutex_lock(&mcu->lock); + ret = iei_wt61p803_puzzle_write_command(mcu, mac_address_cmd, + sizeof(mac_address_cmd), resp_buf, &reply_size); + if (ret) + goto err; + if (reply_size != 3) { + ret = -EIO; + goto err; + } + if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && + resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && + resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) { + ret = -EPROTO; + goto err; + } + + sprintf(mcu->version.mac_address[mac_address_idx], "%.*s", + IEI_WT61P803_PUZZLE_VERSION_MAC_LENGTH, mac_address); +err: + mutex_unlock(&mcu->lock); + return ret; +} + +static int iei_wt61p803_puzzle_write_power_loss_recovery(struct iei_wt61p803_puzzle *mcu, + int power_loss_recovery_action) +{ + unsigned char power_loss_recovery_cmd[5] = { + IEI_WT61P803_PUZZLE_CMD_HEADER_START, + IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER, + IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_POWER_LOSS, + '0' + }; + unsigned char *resp_buf = mcu->response_buffer; + unsigned char cmd_buf[2]; + size_t reply_size = 0; + int ret; + + if (power_loss_recovery_action < 0 || power_loss_recovery_action > 4) + return -EINVAL; + + ret = snprintf(cmd_buf, sizeof(cmd_buf), "%d", power_loss_recovery_action); + if (ret < 0) + return ret; + + /* Modify the command with the action index */ + power_loss_recovery_cmd[3] = cmd_buf[0]; + + mutex_lock(&mcu->lock); + ret = iei_wt61p803_puzzle_write_command(mcu, power_loss_recovery_cmd, + sizeof(power_loss_recovery_cmd), resp_buf, &reply_size); + if (ret) + goto exit; + mcu->status.power_loss_recovery = power_loss_recovery_action; +exit: + mutex_unlock(&mcu->lock); + return ret; +} + +#define sysfs_container(dev) \ + (container_of((dev)->kobj.parent, struct device, kobj)) + +static ssize_t version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct device *dev_container = sysfs_container(dev); + struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev_container); + + return sprintf(buf, "%s\n", mcu->version.version); +} +static DEVICE_ATTR_RO(version); + +static ssize_t build_info_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct device *dev_container = sysfs_container(dev); + struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev_container); + + return sprintf(buf, "%s\n", mcu->version.build_info); +} +static DEVICE_ATTR_RO(build_info); + +static ssize_t bootloader_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct device *dev_container = sysfs_container(dev); + struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev_container); + + return sprintf(buf, "%d\n", mcu->version.bootloader_mode); +} +static DEVICE_ATTR_RO(bootloader_mode); + +static ssize_t protocol_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct device *dev_container = sysfs_container(dev); + struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev_container); + + return sprintf(buf, "%s\n", mcu->version.protocol_version); +} +static DEVICE_ATTR_RO(protocol_version); + +static ssize_t serial_number_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct device *dev_container = sysfs_container(dev); + struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev_container); + int ret; + + mutex_lock(&mcu->lock); + ret = sprintf(buf, "%s\n", mcu->version.serial_number); + mutex_unlock(&mcu->lock); + + return ret; +} +static ssize_t serial_number_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned char serial_number[IEI_WT61P803_PUZZLE_VERSION_SN_LENGTH]; + struct device *dev_container = sysfs_container(dev); + struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev_container); + int ret; + + if ((int)count != IEI_WT61P803_PUZZLE_VERSION_SN_LENGTH + 1) + return -EINVAL; + + memcpy(serial_number, (unsigned char *)buf, IEI_WT61P803_PUZZLE_VERSION_SN_LENGTH); + + ret = iei_wt61p803_puzzle_write_serial_number(mcu, serial_number); + if (ret) + return ret; + + return count; +} +static DEVICE_ATTR_RW(serial_number); + +static ssize_t mac_address_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct device *dev_container = sysfs_container(dev); + struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev_container); + int idx, ret; + + mutex_lock(&mcu->lock); + + if (strlen(attr->attr.name) != 13) + return -EIO; + + idx = attr->attr.name[12] - '0'; + if (idx < 0 || idx > 7) + return -EIO; + + ret = sprintf(buf, "%s\n", mcu->version.mac_address[idx]); + + mutex_unlock(&mcu->lock); + return ret; +} +static ssize_t mac_address_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned char mac_address[IEI_WT61P803_PUZZLE_VERSION_MAC_LENGTH]; + struct device *dev_container = sysfs_container(dev); + struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev_container); + int idx, ret; + + if ((int)count != 17 + 1) + return -EINVAL; + + memcpy(mac_address, (unsigned char *)buf, IEI_WT61P803_PUZZLE_VERSION_MAC_LENGTH); + + if (strlen(attr->attr.name) != 13) + return -EIO; + + idx = attr->attr.name[12] - '0'; + if (idx < 0 || idx > 7) + return -EIO; + + ret = iei_wt61p803_puzzle_write_mac_address(mcu, mac_address, idx); + if (ret) + return ret; + + return count; +} +static DEVICE_ATTR(mac_address_0, 0644, mac_address_show, mac_address_store); +static DEVICE_ATTR(mac_address_1, 0644, mac_address_show, mac_address_store); +static DEVICE_ATTR(mac_address_2, 0644, mac_address_show, mac_address_store); +static DEVICE_ATTR(mac_address_3, 0644, mac_address_show, mac_address_store); +static DEVICE_ATTR(mac_address_4, 0644, mac_address_show, mac_address_store); +static DEVICE_ATTR(mac_address_5, 0644, mac_address_show, mac_address_store); +static DEVICE_ATTR(mac_address_6, 0644, mac_address_show, mac_address_store); +static DEVICE_ATTR(mac_address_7, 0644, mac_address_show, mac_address_store); + +static ssize_t ac_recovery_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct device *dev_container = sysfs_container(dev); + struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev_container); + + int ret; + + ret = iei_wt61p803_puzzle_get_mcu_status(mcu); + if (ret) + return ret; + + mutex_lock(&mcu->lock); + ret = sprintf(buf, "%x\n", mcu->status.ac_recovery_status_flag); + mutex_unlock(&mcu->lock); + + return ret; +} +static DEVICE_ATTR_RO(ac_recovery_status); + +static ssize_t power_loss_recovery_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct device *dev_container = sysfs_container(dev); + struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev_container); + + int ret; + + ret = iei_wt61p803_puzzle_get_mcu_status(mcu); + if (ret) + return ret; + + mutex_lock(&mcu->lock); + ret = sprintf(buf, "%x\n", mcu->status.power_loss_recovery); + mutex_unlock(&mcu->lock); + + return ret; +} +static ssize_t power_loss_recovery_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct device *dev_container = sysfs_container(dev); + struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev_container); + + int ret; + long power_loss_recovery_action = 0; + + ret = kstrtol(buf, 10, &power_loss_recovery_action); + if (ret) + return ret; + + ret = iei_wt61p803_puzzle_write_power_loss_recovery(mcu, + (int)power_loss_recovery_action); + if (ret) + return ret; + + return count; +} +static DEVICE_ATTR_RW(power_loss_recovery); + +static ssize_t power_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct device *dev_container = sysfs_container(dev); + struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev_container); + + int ret; + + ret = iei_wt61p803_puzzle_get_mcu_status(mcu); + if (ret) + return ret; + + mutex_lock(&mcu->lock); + ret = sprintf(buf, "%x\n", mcu->status.power_status); + mutex_unlock(&mcu->lock); + + return ret; +} +static DEVICE_ATTR_RO(power_status); + +static struct attribute *iei_wt61p803_puzzle_attrs[] = { + &dev_attr_version.attr, + &dev_attr_build_info.attr, + &dev_attr_bootloader_mode.attr, + &dev_attr_protocol_version.attr, + &dev_attr_serial_number.attr, + &dev_attr_mac_address_0.attr, + &dev_attr_mac_address_1.attr, + &dev_attr_mac_address_2.attr, + &dev_attr_mac_address_3.attr, + &dev_attr_mac_address_4.attr, + &dev_attr_mac_address_5.attr, + &dev_attr_mac_address_6.attr, + &dev_attr_mac_address_7.attr, + &dev_attr_ac_recovery_status.attr, + &dev_attr_power_loss_recovery.attr, + &dev_attr_power_status.attr, + NULL +}; +ATTRIBUTE_GROUPS(iei_wt61p803_puzzle); + +static int iei_wt61p803_puzzle_sysfs_create(struct device *dev, + struct iei_wt61p803_puzzle *mcu) +{ + int ret; + + mcu->kobj = kobject_create_and_add("iei_wt61p803_puzzle_core", &dev->kobj); + if (!mcu->kobj) + return -ENOMEM; + + ret = sysfs_create_groups(mcu->kobj, iei_wt61p803_puzzle_groups); + if (ret) { + kobject_del(mcu->kobj); + kobject_put(mcu->kobj); + mcu->kobj = NULL; + } + + return ret; +} + +static int iei_wt61p803_puzzle_sysfs_remove(struct device *dev, + struct iei_wt61p803_puzzle *mcu) +{ + /* Remove sysfs groups */ + sysfs_remove_groups(mcu->kobj, iei_wt61p803_puzzle_groups); + + /* Remove the kobject */ + kobject_del(mcu->kobj); + kobject_put(mcu->kobj); + mcu->kobj = NULL; + + return 0; +} + +static int iei_wt61p803_puzzle_probe(struct serdev_device *serdev) +{ + struct device *dev = &serdev->dev; + struct iei_wt61p803_puzzle *mcu; + u32 baud; + int ret; + + /* Read the baud rate from 'current-speed', because the MCU supports different rates */ + if (device_property_read_u32(dev, "current-speed", &baud)) { + dev_err(dev, + "'current-speed' is not specified in device node\n"); + return -EINVAL; + } + dev_info(dev, "Driver baud rate: %d", baud); + + /* Allocate the memory */ + mcu = devm_kzalloc(dev, sizeof(*mcu), GFP_KERNEL); + if (!mcu) + return -ENOMEM; + + mcu->reply = devm_kzalloc(dev, sizeof(*mcu->reply), GFP_KERNEL); + if (!mcu->reply) + return -ENOMEM; + + mcu->reply->data = devm_kzalloc(dev, IEI_WT61P803_PUZZLE_RESP_BUF_SIZE, + GFP_KERNEL); + if (!mcu->reply->data) + return -ENOMEM; + + mcu->response_buffer = devm_kzalloc(dev, IEI_WT61P803_PUZZLE_BUF_SIZE, + GFP_KERNEL); + if (!mcu->response_buffer) + return -ENOMEM; + + /* Initialize device struct data */ + mcu->serdev = serdev; + init_completion(&mcu->reply->received); + mutex_init(&mcu->reply_lock); + mutex_init(&mcu->bus_lock); + mutex_init(&mcu->lock); + + /* Setup UART interface */ + serdev_device_set_drvdata(serdev, mcu); + serdev_device_set_client_ops(serdev, &iei_wt61p803_puzzle_serdev_device_ops); + ret = devm_serdev_device_open(dev, serdev); + if (ret) + return ret; + serdev_device_set_baudrate(serdev, baud); + serdev_device_set_flow_control(serdev, false); + ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE); + if (ret) { + dev_err(dev, "Failed to set parity"); + return ret; + } + + ret = iei_wt61p803_puzzle_get_version(mcu); + if (ret) + return ret; + + ret = iei_wt61p803_puzzle_get_mac_addresses(mcu); + if (ret) + return ret; + + ret = iei_wt61p803_puzzle_get_serial_number(mcu); + if (ret) + return ret; + + dev_info(dev, "MCU version: %s", mcu->version.version); + dev_info(dev, "MCU firmware build info: %s", mcu->version.build_info); + dev_info(dev, "MCU in bootloader mode: %s", + mcu->version.bootloader_mode ? "true" : "false"); + dev_info(dev, "MCU protocol version: %s", mcu->version.protocol_version); + + if (device_property_read_bool(dev, "enable-beep")) { + ret = iei_wt61p803_puzzle_buzzer(mcu, false); + if (ret) + return ret; + } + + ret = iei_wt61p803_puzzle_sysfs_create(dev, mcu); + + return devm_of_platform_populate(dev); +} + +static void iei_wt61p803_puzzle_remove(struct serdev_device *serdev) +{ + struct device *dev = &serdev->dev; + struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev); + + iei_wt61p803_puzzle_sysfs_remove(dev, mcu); +} + +static const struct of_device_id iei_wt61p803_puzzle_dt_ids[] = { + { .compatible = "iei,wt61p803-puzzle" }, + { } +}; + +MODULE_DEVICE_TABLE(of, iei_wt61p803_puzzle_dt_ids); + +static struct serdev_device_driver iei_wt61p803_puzzle_drv = { + .probe = iei_wt61p803_puzzle_probe, + .remove = iei_wt61p803_puzzle_remove, + .driver = { + .name = "iei-wt61p803-puzzle", + .of_match_table = iei_wt61p803_puzzle_dt_ids, + }, +}; + +module_serdev_device_driver(iei_wt61p803_puzzle_drv); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Luka Kovacic "); +MODULE_DESCRIPTION("iEi WT61P803 PUZZLE MCU Driver"); diff --git a/include/linux/mfd/iei-wt61p803-puzzle.h b/include/linux/mfd/iei-wt61p803-puzzle.h new file mode 100644 index 000000000000..633ceb1d00e3 --- /dev/null +++ b/include/linux/mfd/iei-wt61p803-puzzle.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* iEi WT61P803 PUZZLE MCU Driver + * System management microcontroller for fan control, temperature sensor reading, + * LED control and system identification on iEi Puzzle series ARM-based appliances. + * + * Copyright (C) 2020 Sartura Ltd. + * Author: Luka Kovacic + */ + +#ifndef _MFD_IEI_WT61P803_PUZZLE_H_ +#define _MFD_IEI_WT61P803_PUZZLE_H_ + +#define IEI_WT61P803_PUZZLE_BUF_SIZE 512 + +/* Command magic numbers */ +#define IEI_WT61P803_PUZZLE_CMD_HEADER_START 0x40 /* @ */ +#define IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER 0x25 /* % */ +#define IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM 0xF7 + +#define IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK 0x30 /* 0 */ +#define IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK 0x70 + +#define IEI_WT61P803_PUZZLE_CMD_EEPROM_READ 0xA1 +#define IEI_WT61P803_PUZZLE_CMD_EEPROM_WRITE 0xA0 + +#define IEI_WT61P803_PUZZLE_CMD_OTHER_VERSION 0x56 /* V */ +#define IEI_WT61P803_PUZZLE_CMD_OTHER_BUILD 0x42 /* B */ +#define IEI_WT61P803_PUZZLE_CMD_OTHER_BOOTLOADER_MODE 0x4D /* M */ +#define IEI_WT61P803_PUZZLE_CMD_OTHER_MODE_BOOTLOADER 0x30 +#define IEI_WT61P803_PUZZLE_CMD_OTHER_MODE_APPS 0x31 +#define IEI_WT61P803_PUZZLE_CMD_OTHER_PROTOCOL_VERSION 0x50 /* P */ + +#define IEI_WT61P803_PUZZLE_CMD_FUNCTION_SINGLE 0x43 /* C */ +#define IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER 0x4F /* O */ +#define IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS 0x53 /* S */ +#define IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_POWER_LOSS 0x41 /* A */ + +#define IEI_WT61P803_PUZZLE_CMD_LED 0x52 /* R */ +#define IEI_WT61P803_PUZZLE_CMD_LED_POWER 0x31 /* 1 */ + +#define IEI_WT61P803_PUZZLE_CMD_TEMP 0x54 /* T */ +#define IEI_WT61P803_PUZZLE_CMD_TEMP_ALL 0x41 /* A */ + +#define IEI_WT61P803_PUZZLE_CMD_FAN 0x46 /* F */ +#define IEI_WT61P803_PUZZLE_CMD_FAN_PWM_0 0x30 +#define IEI_WT61P803_PUZZLE_CMD_FAN_PWM_1 0x31 +#define IEI_WT61P803_PUZZLE_CMD_FAN_PWM_READ 0x5A /* Z */ +#define IEI_WT61P803_PUZZLE_CMD_FAN_PWM_WRITE 0x57 /* W */ +#define IEI_WT61P803_PUZZLE_CMD_FAN_RPM_0 0x41 /* A */ +#define IEI_WT61P803_PUZZLE_CMD_FAN_RPM_1 0x42 /* B */ +#define IEI_WT61P803_PUZZLE_CMD_FAN_RPM_2 0x43 /* C */ +#define IEI_WT61P803_PUZZLE_CMD_FAN_RPM_3 0x44 /* D */ +#define IEI_WT61P803_PUZZLE_CMD_FAN_RPM_4 0x45 /* E */ +#define IEI_WT61P803_PUZZLE_CMD_FAN_RPM_5 0x46 /* F */ + +struct iei_wt61p803_puzzle_mcu_version; +struct iei_wt61p803_puzzle_reply; +struct iei_wt61p803_puzzle; + +int iei_wt61p803_puzzle_write_command_watchdog(struct iei_wt61p803_puzzle *mcu, + unsigned char *cmd, size_t size, + unsigned char *reply_data, size_t *reply_size, + int retry_count); + +int iei_wt61p803_puzzle_write_command(struct iei_wt61p803_puzzle *mcu, + unsigned char *cmd, size_t size, + unsigned char *reply_data, size_t *reply_size); + +#endif /* _MFD_IEI_WT61P803_PUZZLE_H_ */ From patchwork Wed Sep 30 01:40:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luka Kovacic X-Patchwork-Id: 11807549 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 78B07139F for ; Wed, 30 Sep 2020 01:41:57 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1A5C020738 for ; Wed, 30 Sep 2020 01:41:57 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="jkB1TVHj"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=sartura-hr.20150623.gappssmtp.com header.i=@sartura-hr.20150623.gappssmtp.com header.b="nmNDjeke" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1A5C020738 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=sartura.hr Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=X5BfIy5PeGTABMoaooebvSwEBR5Vu4EmsSLMLPG1egk=; b=jkB1TVHjvrNqbgU9SOp9qNVb/ Md1D0onYRC0IkWz5nPbYCxIRaysf6OEHogotLuby31Nv32eaK/vOq0bo3ms/0NU2bd+BnNJ8BBqIp EVqOt0NWD93qYxTYjf6Sxp1UfyqhE2yqaafS9wCFEyBpaJas3YwA6RXkkLtNAZNLI1C1sIav85f9H fnojRFANJaz7iRh2/6v6UZBotv+AEbChEy84LBW7OSAWOfdH0smmlEdTbBQxCWnEnhhh0rRrm9RWu svolnNBUraTNpkY2mYtvANgx5r5+lbe/lgZ2CsUVMQVKkY5tXRbcWd+BuKqWoFqDjwXqgfq3E+H6K oLPNQIFgA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kNR7l-0000Jo-9H; Wed, 30 Sep 2020 01:41:41 +0000 Received: from mail-ej1-x644.google.com ([2a00:1450:4864:20::644]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kNR7P-0000Dh-7P for linux-arm-kernel@lists.infradead.org; Wed, 30 Sep 2020 01:41:22 +0000 Received: by mail-ej1-x644.google.com with SMTP id p15so416752ejm.7 for ; Tue, 29 Sep 2020 18:41:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sartura-hr.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FuidiMlloV7rQD3tHI0jgrmBm7wWwMcHXMWm1Kz5L9A=; b=nmNDjekelX7Df7z6RSP+Cka1a8Sk6b9KATK7wNovW2teCCyEQn/rmTi8em+pI3jFlB 0guGvt5ABB82u8TH+mgRFmNOxA4VakiS7sP7F+USO0KcXhw86zZiGVhY8QblgPpUW5LK JjFfND2znUK2HAK0vyXu/TpXZWLjAWN6kzp/JoOpxnLW+Awv4g65gMQJ+kTdyofYTan4 sy1eWu+1Z9U0nPStbeUKD4/GqwLQeqSP6dlLibya89TjEYazJGQuCbHppdjJQQg3BnUB Gk80HY23yi1x+X5AE/5BCpwg7u/ZPPciyzg38VVtkudKv7eAbIT1ZBwFlkPdtA5oWAso /c4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=FuidiMlloV7rQD3tHI0jgrmBm7wWwMcHXMWm1Kz5L9A=; b=RlSiyQU4N5GJebmaaZjVlOfLHT7NaT2PA2aZpO/LNodU5XtB3bynL8Y37AxVraCoyq ukbYJiyVxwQneAcoL5ifTNSCznAK1QYmy1XyNlep203L1Mg+9wxq2dyAcx0PClgjdigl o1Ewx2rSKT/oxuhPHIw6euM5Gzr//g7IGVO9f/F3x+Y4vXmUkgbpYY3HJJArcs9kRbcI 5ey6spF7bq9jHyNKUO3GEgx4aopwLMssvpQi/HG3hcngmlcUjvsVke23lv74+KsoG3Yh wrbCQ/B7J0pL5hqMLAXMHPlqsjmTuScQJz93m/XmaGMn71eGGg7WJS0K9qDh/mimRVBI qZ2A== X-Gm-Message-State: AOAM532VcSqK54BKZDZHka+rYt1HVWbjr0lYs/dFc3nzvQAqeKlGmzE+ 6/2843tmGwQCg4JSSVr+BCHZMg== X-Google-Smtp-Source: ABdhPJzaKAsMdK2QkP07L2fNrkxPfh+u4dF2LjbTkvqBStdh6q52dGVk6aj2ttmJSHcdxYi8Yo9WiA== X-Received: by 2002:a17:906:3495:: with SMTP id g21mr443849ejb.121.1601430078283; Tue, 29 Sep 2020 18:41:18 -0700 (PDT) Received: from localhost.localdomain ([2a00:ee2:4b0d:3000:290:faff:fe54:449c]) by smtp.gmail.com with ESMTPSA id q1sm203258ejy.37.2020.09.29.18.41.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Sep 2020 18:41:17 -0700 (PDT) From: Luka Kovacic To: linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-leds@vger.kernel.org Subject: [PATCH v3 3/7] drivers: hwmon: Add the iEi WT61P803 PUZZLE HWMON driver Date: Wed, 30 Sep 2020 03:40:54 +0200 Message-Id: <20200930014058.44460-4-luka.kovacic@sartura.hr> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200930014058.44460-1-luka.kovacic@sartura.hr> References: <20200930014058.44460-1-luka.kovacic@sartura.hr> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200929_214119_381779_03D2FEAF X-CRM114-Status: GOOD ( 27.39 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:644 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: andrew@lunn.ch, jdelvare@suse.com, luka.perkov@sartura.hr, jason@lakedaemon.net, gregory.clement@bootlin.com, marek.behun@nic.cz, Luka Kovacic , robh+dt@kernel.org, dmurphy@ti.com, pavel@ucw.cz, robert.marko@sartura.hr, lee.jones@linaro.org, linux@roeck-us.net Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Add the iEi WT61P803 PUZZLE HWMON driver, that handles the fan speed control via PWM, reading fan speed and reading on-board temperature sensors. The driver registers a HWMON device and a simple thermal cooling device to enable in-kernel fan management. This driver depends on the iEi WT61P803 PUZZLE MFD driver. Signed-off-by: Luka Kovacic Cc: Luka Perkov Cc: Robert Marko --- drivers/hwmon/Kconfig | 8 + drivers/hwmon/Makefile | 1 + drivers/hwmon/iei-wt61p803-puzzle-hwmon.c | 513 ++++++++++++++++++++++ 3 files changed, 522 insertions(+) create mode 100644 drivers/hwmon/iei-wt61p803-puzzle-hwmon.c diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 8dc28b26916e..ff279df9bf40 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -722,6 +722,14 @@ config SENSORS_IBMPOWERNV This driver can also be built as a module. If so, the module will be called ibmpowernv. +config SENSORS_IEI_WT61P803_PUZZLE_HWMON + tristate "iEi WT61P803 PUZZLE MFD HWMON Driver" + depends on MFD_IEI_WT61P803_PUZZLE + help + The iEi WT61P803 PUZZLE MFD HWMON Driver handles reading fan speed + and writing fan PWM values. It also supports reading on-board + temperature sensors. + config SENSORS_IIO_HWMON tristate "Hwmon driver that uses channels specified via iio maps" depends on IIO diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index a8f4b35b136b..b0afb2d6896f 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -83,6 +83,7 @@ obj-$(CONFIG_SENSORS_HIH6130) += hih6130.o obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o obj-$(CONFIG_SENSORS_I5500) += i5500_temp.o obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o +obj-$(CONFIG_SENSORS_IEI_WT61P803_PUZZLE_HWMON) += iei-wt61p803-puzzle-hwmon.o obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o obj-$(CONFIG_SENSORS_IBMPOWERNV)+= ibmpowernv.o diff --git a/drivers/hwmon/iei-wt61p803-puzzle-hwmon.c b/drivers/hwmon/iei-wt61p803-puzzle-hwmon.c new file mode 100644 index 000000000000..990016329578 --- /dev/null +++ b/drivers/hwmon/iei-wt61p803-puzzle-hwmon.c @@ -0,0 +1,513 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* iEi WT61P803 PUZZLE MCU HWMON Driver + * + * Copyright (C) 2020 Sartura Ltd. + * Author: Luka Kovacic + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IEI_WT61P803_PUZZLE_HWMON_MAX_TEMP_NUM 2 +#define IEI_WT61P803_PUZZLE_HWMON_MAX_FAN_NUM 5 +#define IEI_WT61P803_PUZZLE_HWMON_MAX_PWM_NUM 2 +#define IEI_WT61P803_PUZZLE_HWMON_MAX_PWM_VAL 255 + +/** + * struct iei_wt61p803_puzzle_thermal_cooling_device - Thermal cooling device instance + * + * @mcu_hwmon: MCU HWMON struct pointer + * @tcdev: Thermal cooling device pointer + * @name: Thermal cooling device name + * @pwm_channel: PWM channel (0 or 1) + * @cooling_levels: Thermal cooling device cooling levels + */ +struct iei_wt61p803_puzzle_thermal_cooling_device { + struct iei_wt61p803_puzzle_hwmon *mcu_hwmon; + struct thermal_cooling_device *tcdev; + char name[THERMAL_NAME_LENGTH]; + int pwm_channel; + u8 *cooling_levels; +}; + +/** + * struct iei_wt61p803_puzzle_hwmon - MCU HWMON Driver + * + * @mcu: MCU struct pointer + * @lock General member lock + * @response_buffer Global MCU response buffer allocation + * @temp_sensor_val: Temperature sensor values + * @fan_speed_val: FAN speed (RPM) values + * @pwm_val: PWM values (0-255) + * @thermal_cooling_dev_present: Per-channel thermal cooling device control + * @cdev: Per-channel thermal cooling device private structure + */ +struct iei_wt61p803_puzzle_hwmon { + struct iei_wt61p803_puzzle *mcu; + struct mutex lock; + unsigned char *response_buffer; + int temp_sensor_val[IEI_WT61P803_PUZZLE_HWMON_MAX_TEMP_NUM]; + int fan_speed_val[IEI_WT61P803_PUZZLE_HWMON_MAX_FAN_NUM]; + int pwm_val[IEI_WT61P803_PUZZLE_HWMON_MAX_PWM_NUM]; + bool thermal_cooling_dev_present[IEI_WT61P803_PUZZLE_HWMON_MAX_PWM_NUM]; + struct iei_wt61p803_puzzle_thermal_cooling_device + *cdev[IEI_WT61P803_PUZZLE_HWMON_MAX_PWM_NUM]; +}; + +#define raw_temp_to_milidegree_celsius(x) ((int)((x - 0x80)*1000)) +static int iei_wt61p803_puzzle_read_temp_sensor +(struct iei_wt61p803_puzzle_hwmon *mcu_hwmon, int channel, int *value) +{ + unsigned char *resp_buf = mcu_hwmon->response_buffer; + unsigned char temp_sensor_ntc_cmd[4] = { + IEI_WT61P803_PUZZLE_CMD_HEADER_START, + IEI_WT61P803_PUZZLE_CMD_TEMP, + IEI_WT61P803_PUZZLE_CMD_TEMP_ALL + }; + size_t reply_size = 0; + int ret; + + if (channel > 1 && channel < 0) + return -EINVAL; + + mutex_lock(&mcu_hwmon->lock); + ret = iei_wt61p803_puzzle_write_command(mcu_hwmon->mcu, + temp_sensor_ntc_cmd, sizeof(temp_sensor_ntc_cmd), + resp_buf, &reply_size); + if (!ret) { + /* Check the number of NTC values (should be 0x32/'2') */ + if (resp_buf[3] == 0x32) { + /* Write values to the struct */ + mcu_hwmon->temp_sensor_val[0] = + raw_temp_to_milidegree_celsius(resp_buf[4]); + mcu_hwmon->temp_sensor_val[1] = + raw_temp_to_milidegree_celsius(resp_buf[5]); + } + + } + *value = mcu_hwmon->temp_sensor_val[channel]; + mutex_unlock(&mcu_hwmon->lock); + + return ret; +} + +#define raw_fan_val_to_rpm(x, y) ((int)(((x)<<8|(y))/2)*60) +static int iei_wt61p803_puzzle_read_fan_speed +(struct iei_wt61p803_puzzle_hwmon *mcu_hwmon, int channel, int *value) +{ + unsigned char *resp_buf = mcu_hwmon->response_buffer; + unsigned char fan_speed_cmd[4] = { + IEI_WT61P803_PUZZLE_CMD_HEADER_START, + IEI_WT61P803_PUZZLE_CMD_FAN, + IEI_WT61P803_PUZZLE_CMD_FAN_RPM_0 + }; + size_t reply_size = 0; + int ret; + + switch (channel) { + case 0: + fan_speed_cmd[2] = IEI_WT61P803_PUZZLE_CMD_FAN_RPM_0; + break; + case 1: + fan_speed_cmd[2] = IEI_WT61P803_PUZZLE_CMD_FAN_RPM_1; + break; + case 2: + fan_speed_cmd[2] = IEI_WT61P803_PUZZLE_CMD_FAN_RPM_2; + break; + case 3: + fan_speed_cmd[2] = IEI_WT61P803_PUZZLE_CMD_FAN_RPM_3; + break; + case 4: + fan_speed_cmd[2] = IEI_WT61P803_PUZZLE_CMD_FAN_RPM_4; + break; + default: + return -EINVAL; + } + + mutex_lock(&mcu_hwmon->lock); + ret = iei_wt61p803_puzzle_write_command(mcu_hwmon->mcu, fan_speed_cmd, + sizeof(fan_speed_cmd), resp_buf, &reply_size); + if (!ret) + mcu_hwmon->fan_speed_val[channel] = raw_fan_val_to_rpm(resp_buf[3], + resp_buf[4]); + + *value = mcu_hwmon->fan_speed_val[channel]; + mutex_unlock(&mcu_hwmon->lock); + + return 0; +} + +static int iei_wt61p803_puzzle_write_pwm_channel +(struct iei_wt61p803_puzzle_hwmon *mcu_hwmon, int channel, long pwm_set_val) +{ + unsigned char *resp_buf = mcu_hwmon->response_buffer; + unsigned char pwm_set_cmd[6] = { + IEI_WT61P803_PUZZLE_CMD_HEADER_START, + IEI_WT61P803_PUZZLE_CMD_FAN, + IEI_WT61P803_PUZZLE_CMD_FAN_PWM_WRITE, + IEI_WT61P803_PUZZLE_CMD_FAN_PWM_0, + 0x00 + }; + size_t reply_size = 0; + int ret; + + switch (channel) { + case 0: + pwm_set_cmd[3] = IEI_WT61P803_PUZZLE_CMD_FAN_PWM_0; + break; + case 1: + pwm_set_cmd[3] = IEI_WT61P803_PUZZLE_CMD_FAN_PWM_1; + break; + default: + return -EINVAL; + } + + if (pwm_set_val < 0 || pwm_set_val > IEI_WT61P803_PUZZLE_HWMON_MAX_PWM_VAL) + return -EINVAL; + + /* Add the PWM value to the command */ + pwm_set_cmd[4] = (char)pwm_set_val; + + mutex_lock(&mcu_hwmon->lock); + ret = iei_wt61p803_puzzle_write_command(mcu_hwmon->mcu, pwm_set_cmd, + sizeof(pwm_set_cmd), resp_buf, &reply_size); + if (!ret) { + /* Store the PWM value */ + if (resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && + resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && + resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK) + mcu_hwmon->pwm_val[channel] = (int)pwm_set_val; + } + mutex_unlock(&mcu_hwmon->lock); + + return 0; +} + +static int iei_wt61p803_puzzle_read_pwm_channel +(struct iei_wt61p803_puzzle_hwmon *mcu_hwmon, int channel, int *value) +{ + unsigned char *resp_buf = mcu_hwmon->response_buffer; + unsigned char pwm_get_cmd[5] = { + IEI_WT61P803_PUZZLE_CMD_HEADER_START, + IEI_WT61P803_PUZZLE_CMD_FAN, + IEI_WT61P803_PUZZLE_CMD_FAN_PWM_READ, + IEI_WT61P803_PUZZLE_CMD_FAN_PWM_0 + }; + size_t reply_size = 0; + int ret; + + switch (channel) { + case 0: + pwm_get_cmd[3] = IEI_WT61P803_PUZZLE_CMD_FAN_PWM_0; + break; + case 1: + pwm_get_cmd[3] = IEI_WT61P803_PUZZLE_CMD_FAN_PWM_1; + break; + default: + return -EINVAL; + } + + mutex_lock(&mcu_hwmon->lock); + ret = iei_wt61p803_puzzle_write_command(mcu_hwmon->mcu, pwm_get_cmd, + sizeof(pwm_get_cmd), resp_buf, &reply_size); + if (!ret) { + /* Store the PWM value */ + if (resp_buf[2] == IEI_WT61P803_PUZZLE_CMD_FAN_PWM_READ) + mcu_hwmon->pwm_val[channel] = (int)resp_buf[3]; + } + *value = mcu_hwmon->pwm_val[channel]; + mutex_unlock(&mcu_hwmon->lock); + + return 0; +} + +static int iei_wt61p803_puzzle_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) +{ + struct iei_wt61p803_puzzle_hwmon *mcu_hwmon = + dev_get_drvdata(dev->parent); + int ret, value; + + switch (type) { + case hwmon_pwm: + if (attr != hwmon_pwm_input) + return -ENODEV; + ret = iei_wt61p803_puzzle_read_pwm_channel(mcu_hwmon, channel, &value); + if (ret) + return ret; + *val = (long)value; + return ret; + case hwmon_fan: + if (attr != hwmon_fan_input) + return -ENODEV; + ret = iei_wt61p803_puzzle_read_fan_speed(mcu_hwmon, channel, &value); + if (ret) + return ret; + *val = (long)value; + return ret; + case hwmon_temp: + if (attr != hwmon_temp_input) + return -ENODEV; + ret = iei_wt61p803_puzzle_read_temp_sensor(mcu_hwmon, channel, &value); + if (ret) + return ret; + *val = (long)value; + return ret; + default: + return -ENODEV; + } +} + +static int iei_wt61p803_puzzle_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long val) +{ + struct iei_wt61p803_puzzle_hwmon *mcu_hwmon = + dev_get_drvdata(dev->parent); + + switch (type) { + case hwmon_pwm: + if (attr != hwmon_pwm_input) + return -ENODEV; + if (mcu_hwmon->thermal_cooling_dev_present[channel]) { + /* + * The Thermal Framework has already claimed this specific PWM + * channel. + */ + return -EBUSY; + } + return iei_wt61p803_puzzle_write_pwm_channel(mcu_hwmon, channel, val); + default: + return -ENODEV; + } +} + +static umode_t iei_wt61p803_puzzle_is_visible(const void *data, + enum hwmon_sensor_types type, u32 attr, int channel) +{ + const struct iei_wt61p803_puzzle_hwmon *mcu_hwmon = data; + + switch (type) { + case hwmon_pwm: + switch (attr) { + case hwmon_pwm_input: + if (mcu_hwmon->thermal_cooling_dev_present[channel]) + return 0444; + return 0644; + default: + return 0; + } + case hwmon_fan: + switch (attr) { + case hwmon_fan_input: + return 0444; + default: + return 0; + } + case hwmon_temp: + switch (attr) { + case hwmon_temp_input: + return 0444; + default: + return 0; + } + default: + return 0; + } +} + +static const struct hwmon_ops iei_wt61p803_puzzle_hwmon_ops = { + .is_visible = iei_wt61p803_puzzle_is_visible, + .read = iei_wt61p803_puzzle_read, + .write = iei_wt61p803_puzzle_write, +}; + +static const struct hwmon_channel_info *iei_wt61p803_puzzle_info[] = { + HWMON_CHANNEL_INFO(pwm, + HWMON_PWM_INPUT, + HWMON_PWM_INPUT), + HWMON_CHANNEL_INFO(fan, + HWMON_F_INPUT, + HWMON_F_INPUT, + HWMON_F_INPUT, + HWMON_F_INPUT, + HWMON_F_INPUT), + HWMON_CHANNEL_INFO(temp, + HWMON_T_INPUT, + HWMON_T_INPUT), + NULL +}; + +static const struct hwmon_chip_info iei_wt61p803_puzzle_chip_info = { + .ops = &iei_wt61p803_puzzle_hwmon_ops, + .info = iei_wt61p803_puzzle_info, +}; + +static int iei_wt61p803_puzzle_get_max_state +(struct thermal_cooling_device *tcdev, unsigned long *state) +{ + *state = IEI_WT61P803_PUZZLE_HWMON_MAX_PWM_VAL; + + return 0; +} +static int iei_wt61p803_puzzle_get_cur_state +(struct thermal_cooling_device *tcdev, unsigned long *state) +{ + struct iei_wt61p803_puzzle_thermal_cooling_device *cdev = tcdev->devdata; + struct iei_wt61p803_puzzle_hwmon *mcu_hwmon = cdev->mcu_hwmon; + + int ret, value; + + if (!mcu_hwmon) + return -EINVAL; + + ret = iei_wt61p803_puzzle_read_pwm_channel(mcu_hwmon, + cdev->pwm_channel, &value); + if (ret) + return ret; + + *state = (unsigned long)value; + + return 0; +} +static int iei_wt61p803_puzzle_set_cur_state +(struct thermal_cooling_device *tcdev, unsigned long state) +{ + struct iei_wt61p803_puzzle_thermal_cooling_device *cdev = tcdev->devdata; + struct iei_wt61p803_puzzle_hwmon *mcu_hwmon = cdev->mcu_hwmon; + + if (!mcu_hwmon) + return -EINVAL; + + return iei_wt61p803_puzzle_write_pwm_channel(mcu_hwmon, + cdev->pwm_channel, state); +} +static const struct thermal_cooling_device_ops iei_wt61p803_puzzle_cooling_ops = { + .get_max_state = iei_wt61p803_puzzle_get_max_state, + .get_cur_state = iei_wt61p803_puzzle_get_cur_state, + .set_cur_state = iei_wt61p803_puzzle_set_cur_state, +}; + +static int iei_wt61p803_puzzle_enable_thermal_cooling_dev +(struct device *dev, struct fwnode_handle *child, struct iei_wt61p803_puzzle_hwmon *mcu_hwmon) +{ + struct iei_wt61p803_puzzle_thermal_cooling_device *cdev; + int ret, num_levels; + u32 pwm_channel; + + ret = fwnode_property_read_u32(child, "reg", &pwm_channel); + if (ret) + return ret; + + mutex_lock(&mcu_hwmon->lock); + mcu_hwmon->thermal_cooling_dev_present[pwm_channel] = true; + mutex_unlock(&mcu_hwmon->lock); + + num_levels = fwnode_property_read_u8_array(child, "cooling-levels", NULL, 0); + if (num_levels > 0) { + cdev = devm_kzalloc(dev, sizeof(*cdev), GFP_KERNEL); + if (!cdev) + return -ENOMEM; + + cdev->cooling_levels = devm_kzalloc(dev, num_levels, GFP_KERNEL); + if (!cdev->cooling_levels) + return -ENOMEM; + + ret = fwnode_property_read_u8_array(child, "cooling-levels", + cdev->cooling_levels, num_levels); + if (ret) { + dev_err(dev, "Couldn't read property 'cooling-levels'"); + return ret; + } + + snprintf(cdev->name, THERMAL_NAME_LENGTH, "iei_wt61p803_puzzle_%d", pwm_channel); + + cdev->tcdev = devm_thermal_of_cooling_device_register(dev, NULL, + cdev->name, cdev, &iei_wt61p803_puzzle_cooling_ops); + if (IS_ERR(cdev->tcdev)) + return PTR_ERR(cdev->tcdev); + + cdev->mcu_hwmon = mcu_hwmon; + cdev->pwm_channel = pwm_channel; + + mutex_lock(&mcu_hwmon->lock); + mcu_hwmon->cdev[pwm_channel] = cdev; + mutex_unlock(&mcu_hwmon->lock); + } + return 0; +} + +static int iei_wt61p803_puzzle_hwmon_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev->parent); + struct iei_wt61p803_puzzle_hwmon *mcu_hwmon; + struct fwnode_handle *child; + struct device *hwmon_dev; + int ret; + + mcu_hwmon = devm_kzalloc(dev, sizeof(*mcu_hwmon), GFP_KERNEL); + if (!mcu_hwmon) + return -ENOMEM; + + mcu_hwmon->response_buffer = devm_kzalloc(dev, + IEI_WT61P803_PUZZLE_BUF_SIZE, GFP_KERNEL); + if (!mcu_hwmon->response_buffer) + return -ENOMEM; + + mcu_hwmon->mcu = mcu; + mutex_init(&mcu_hwmon->lock); + platform_set_drvdata(pdev, mcu_hwmon); + + hwmon_dev = devm_hwmon_device_register_with_info(dev, + "iei_wt61p803_puzzle", + mcu_hwmon, + &iei_wt61p803_puzzle_chip_info, + NULL); + + if (IS_ERR(hwmon_dev)) + return PTR_ERR(hwmon_dev); + + /* Control fans via PWM lines via Linux Kernel */ + if (IS_ENABLED(CONFIG_THERMAL)) { + device_for_each_child_node(dev, child) { + ret = iei_wt61p803_puzzle_enable_thermal_cooling_dev(dev, child, mcu_hwmon); + if (ret) { + dev_err(dev, "Enabling the PWM fan failed\n"); + fwnode_handle_put(child); + return ret; + } + } + } + return 0; +} + +static const struct of_device_id iei_wt61p803_puzzle_hwmon_id_table[] = { + { .compatible = "iei,wt61p803-puzzle-hwmon" }, + {} +}; +MODULE_DEVICE_TABLE(of, iei_wt61p803_puzzle_hwmon_id_table); + +static struct platform_driver iei_wt61p803_puzzle_hwmon_driver = { + .driver = { + .name = "iei-wt61p803-puzzle-hwmon", + .of_match_table = iei_wt61p803_puzzle_hwmon_id_table, + }, + .probe = iei_wt61p803_puzzle_hwmon_probe, +}; + +module_platform_driver(iei_wt61p803_puzzle_hwmon_driver); + +MODULE_DESCRIPTION("iEi WT61P803 PUZZLE MCU HWMON Driver"); +MODULE_AUTHOR("Luka Kovacic "); +MODULE_LICENSE("GPL"); From patchwork Wed Sep 30 01:40:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luka Kovacic X-Patchwork-Id: 11807557 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 431341668 for ; Wed, 30 Sep 2020 01:43:25 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 078D820B1F for ; Wed, 30 Sep 2020 01:43:24 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="pLQWH65x"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=sartura-hr.20150623.gappssmtp.com header.i=@sartura-hr.20150623.gappssmtp.com header.b="L5pF50Ti" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 078D820B1F Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=sartura.hr Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=C+qTlxcVHJ1KvXopCuJmt2N7P6pyI+BnROjYZ1Ml/bo=; b=pLQWH65xmerLXbaxElGfc8Alv Cdy3Mhqd0eyvaz4A6/bMdHWZQi4Cfef8WgEzg9uZR51vyhZOzaIItKdQTHUb00P5vDObDe9wKfZ5m JErEPv7HlH7f7JYcDpeRb41+8QP+IOAN2yccBMppPVoulhxVRKF2vbuFyJ4XmcmR9XMt1ZMC+C8Au MCfctp3TjDSTEisf8u5Zgg8q6ZIkvfKPqo5WGH5L60F4tKw2rGeT6Ru5ohHALb8jWojp3+zYF9T6o VYmOUZ5f9jXZR8Go9owiRHYXms1f8YbVJgR+LVjQFBoYF8tKjg3B4SahF9Zmlkb8ECEcSDEf1C4vl y9bvNJAig==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kNR7u-0000Mv-Fi; Wed, 30 Sep 2020 01:41:50 +0000 Received: from mail-ej1-x641.google.com ([2a00:1450:4864:20::641]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kNR7R-0000E9-6D for linux-arm-kernel@lists.infradead.org; Wed, 30 Sep 2020 01:41:24 +0000 Received: by mail-ej1-x641.google.com with SMTP id i26so388841ejb.12 for ; Tue, 29 Sep 2020 18:41:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sartura-hr.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=JBnUFnJSOFEGYo9H4MHI7job+37X4slQh33wij3Ffq4=; b=L5pF50TiwtNbHMdxCVqeFPFshOtBqzN9jXMRvibFj3hKtTWs2Fbg3hC4HjtcThsveE fpQ3p3JV5eFwD7ugMDX0ygRY0xUtKkJxy/jNYq0azyjCNvljzIxsjsoNyNkaYcaN0uMn mALj4Y5LjG81rX9WYOF/Hf0dEcaHh6wCRW+SkkV6ZlVNV33MX6F1shqZmpT6jaEQ7bsJ neWKhk9GBuJ/afUmQL0DEk7xpfGpoByGG0QzzcUjbKZ27H6pxyNU+PnFStez2iwY0cBq Xh8AQ2Sh/uNmP1p3OYMsivTd9cVe7g8nW7Q+U9mTh5lxwXanE1zl63vXNJcQAg1X0au5 DgOA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=JBnUFnJSOFEGYo9H4MHI7job+37X4slQh33wij3Ffq4=; b=bbSveYenFX+WOjarIwkUc9RBnrhx8D2oIIEgWs0sPgEe5F/6zOMqbYPdJHfIVWAdQi WzbGndbnsxai9EoQ0ZX0uV+SmJ83fQlY8PM+vPtOdUdM+xQivtFGjxAN6JX2KC+i76aG SpJObTJgGYPGl/dldaeAAOV9BJgYpfL8SJ0NSrdbWU8UCqQBKvsAh/eKb4688J+2ZWFD TGNYcGI3E+O06YgUHOF034uRFohSTgvFqSvOhInygQdv6kauLZyYdMN8SzFXfBpFbIwG +Vj/OEQs/+OK4otWBnREFzI/UZSDnvD3nxYhdlcMdq3uuXIaUY+zo8COSkn12rYYX2lX YKrQ== X-Gm-Message-State: AOAM532hk3mKyjPsR7DUgYKA4fH+krKsyhs85uhf07Pn92IQ1DAHcx9O 9lAlR+QWIMN4rXyneVtbDOHx2A== X-Google-Smtp-Source: ABdhPJwTTeDEvyQkzrzl7X0r6dtd04JcYVVRYvNwohWDpUMutl9XbFBFpVGXhDvxCbUxeiUOoAN+vw== X-Received: by 2002:a17:906:fb15:: with SMTP id lz21mr461208ejb.185.1601430079860; Tue, 29 Sep 2020 18:41:19 -0700 (PDT) Received: from localhost.localdomain ([2a00:ee2:4b0d:3000:290:faff:fe54:449c]) by smtp.gmail.com with ESMTPSA id q1sm203258ejy.37.2020.09.29.18.41.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Sep 2020 18:41:19 -0700 (PDT) From: Luka Kovacic To: linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-leds@vger.kernel.org Subject: [PATCH v3 4/7] drivers: leds: Add the iEi WT61P803 PUZZLE LED driver Date: Wed, 30 Sep 2020 03:40:55 +0200 Message-Id: <20200930014058.44460-5-luka.kovacic@sartura.hr> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200930014058.44460-1-luka.kovacic@sartura.hr> References: <20200930014058.44460-1-luka.kovacic@sartura.hr> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200929_214121_281564_90F72657 X-CRM114-Status: GOOD ( 24.66 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:641 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: andrew@lunn.ch, jdelvare@suse.com, luka.perkov@sartura.hr, jason@lakedaemon.net, gregory.clement@bootlin.com, marek.behun@nic.cz, Luka Kovacic , robh+dt@kernel.org, dmurphy@ti.com, pavel@ucw.cz, robert.marko@sartura.hr, lee.jones@linaro.org, linux@roeck-us.net Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Add support for the iEi WT61P803 PUZZLE LED driver. Currently only the front panel power LED is supported. This driver depends on the iEi WT61P803 PUZZLE MFD driver. Signed-off-by: Luka Kovacic Cc: Luka Perkov Cc: Robert Marko --- drivers/leds/Kconfig | 8 ++ drivers/leds/Makefile | 1 + drivers/leds/leds-iei-wt61p803-puzzle.c | 157 ++++++++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 drivers/leds/leds-iei-wt61p803-puzzle.c diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 1c181df24eae..8a25fb753dec 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -332,6 +332,14 @@ config LEDS_IPAQ_MICRO Choose this option if you want to use the notification LED on Compaq/HP iPAQ h3100 and h3600. +config LEDS_IEI_WT61P803_PUZZLE + tristate "LED Support for the iEi WT61P803 PUZZLE MCU" + depends on LEDS_CLASS + depends on MFD_IEI_WT61P803_PUZZLE + help + This option enables support for LEDs controlled by the iEi WT61P803 + M801 MCU. + config LEDS_HP6XX tristate "LED Support for the HP Jornada 6xx" depends on LEDS_CLASS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index c2c7d7ade0d0..cd362437fefd 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o obj-$(CONFIG_LEDS_INTEL_SS4200) += leds-ss4200.o obj-$(CONFIG_LEDS_IP30) += leds-ip30.o obj-$(CONFIG_LEDS_IPAQ_MICRO) += leds-ipaq-micro.o +obj-$(CONFIG_LEDS_IEI_WT61P803_PUZZLE) += leds-iei-wt61p803-puzzle.o obj-$(CONFIG_LEDS_IS31FL319X) += leds-is31fl319x.o obj-$(CONFIG_LEDS_IS31FL32XX) += leds-is31fl32xx.o obj-$(CONFIG_LEDS_KTD2692) += leds-ktd2692.o diff --git a/drivers/leds/leds-iei-wt61p803-puzzle.c b/drivers/leds/leds-iei-wt61p803-puzzle.c new file mode 100644 index 000000000000..b5822a835116 --- /dev/null +++ b/drivers/leds/leds-iei-wt61p803-puzzle.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* iEi WT61P803 PUZZLE MCU LED Driver + * + * Copyright (C) 2020 Sartura Ltd. + * Author: Luka Kovacic + */ + +#include +#include +#include +#include +#include +#include +#include + +enum iei_wt61p803_puzzle_led_state { + IEI_LED_OFF = 0x30, + IEI_LED_ON = 0x31, + IEI_LED_BLINK_5HZ = 0x32, + IEI_LED_BLINK_1HZ = 0x33, +}; + +/** + * struct iei_wt61p803_puzzle_led - MCU LED Driver + * + * @mcu: MCU struct pointer + * @response_buffer Global MCU response buffer allocation + * @lock: General mutex lock for LED operations + * @led_power_state: State of the front panel power LED + * @cdev: LED classdev + */ +struct iei_wt61p803_puzzle_led { + struct iei_wt61p803_puzzle *mcu; + unsigned char *response_buffer; + struct mutex lock; + int led_power_state; + struct led_classdev cdev; +}; + +static inline struct iei_wt61p803_puzzle_led *cdev_to_iei_wt61p803_puzzle_led + (struct led_classdev *led_cdev) +{ + return dev_get_drvdata(led_cdev->dev->parent); +} + +static int iei_wt61p803_puzzle_led_brightness_set_blocking(struct led_classdev *cdev, + enum led_brightness brightness) +{ + struct iei_wt61p803_puzzle_led *priv = cdev_to_iei_wt61p803_puzzle_led(cdev); + unsigned char *resp_buf = priv->response_buffer; + unsigned char led_power_cmd[5] = { + IEI_WT61P803_PUZZLE_CMD_HEADER_START, + IEI_WT61P803_PUZZLE_CMD_LED, + IEI_WT61P803_PUZZLE_CMD_LED_POWER, + (char)IEI_LED_OFF + }; + size_t reply_size; + + mutex_lock(&priv->lock); + if (brightness == LED_OFF) { + led_power_cmd[3] = (char)IEI_LED_OFF; + priv->led_power_state = LED_OFF; + } else { + led_power_cmd[3] = (char)IEI_LED_ON; + priv->led_power_state = LED_ON; + } + mutex_unlock(&priv->lock); + + return iei_wt61p803_puzzle_write_command(priv->mcu, led_power_cmd, + sizeof(led_power_cmd), resp_buf, &reply_size); +} + +static enum led_brightness +iei_wt61p803_puzzle_led_brightness_get(struct led_classdev *cdev) +{ + struct iei_wt61p803_puzzle_led *priv = + cdev_to_iei_wt61p803_puzzle_led(cdev); + int led_state; + + mutex_lock(&priv->lock); + led_state = priv->led_power_state; + mutex_unlock(&priv->lock); + + return led_state; +} + +static int iei_wt61p803_puzzle_led_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev->parent); + struct iei_wt61p803_puzzle_led *priv; + struct led_init_data init_data = {}; + struct fwnode_handle *child; + int ret; + u32 reg; + + if (device_get_child_node_count(dev) != 1) + return -EINVAL; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->response_buffer = devm_kzalloc(dev, + IEI_WT61P803_PUZZLE_BUF_SIZE, GFP_KERNEL); + if (!priv->response_buffer) + return -ENOMEM; + + priv->mcu = mcu; + priv->led_power_state = 1; + mutex_init(&priv->lock); + dev_set_drvdata(dev, priv); + + child = device_get_next_child_node(dev, NULL); + + ret = fwnode_property_read_u32(child, "reg", ®); + if (ret || reg > 1) { + dev_err(dev, "Could not register 'reg' (%lu)\n", (unsigned long)reg); + ret = -EINVAL; + goto err_child_node; + } + + priv->cdev.brightness_set_blocking = iei_wt61p803_puzzle_led_brightness_set_blocking; + priv->cdev.brightness_get = iei_wt61p803_puzzle_led_brightness_get; + priv->cdev.max_brightness = 1; + init_data.fwnode = child; + + ret = devm_led_classdev_register_ext(dev, &priv->cdev, &init_data); + if (ret) { + dev_err(dev, "Could not register LED\n"); + goto err_child_node; + } + return 0; +err_child_node: + fwnode_handle_put(child); + return ret; +} + +static const struct of_device_id iei_wt61p803_puzzle_led_of_match[] = { + { .compatible = "iei,wt61p803-puzzle-leds" }, + { } +}; +MODULE_DEVICE_TABLE(of, iei_wt61p803_puzzle_led_of_match); + +static struct platform_driver iei_wt61p803_puzzle_led_driver = { + .driver = { + .name = "iei-wt61p803-puzzle-led", + .of_match_table = iei_wt61p803_puzzle_led_of_match, + }, + .probe = iei_wt61p803_puzzle_led_probe, +}; +module_platform_driver(iei_wt61p803_puzzle_led_driver); + +MODULE_DESCRIPTION("iEi WT61P803 PUZZLE front panel LED driver"); +MODULE_AUTHOR("Luka Kovacic "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:leds-iei-wt61p803-puzzle"); From patchwork Wed Sep 30 01:40:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luka Kovacic X-Patchwork-Id: 11807551 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1E2826CB for ; Wed, 30 Sep 2020 01:42:15 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CD85520C09 for ; Wed, 30 Sep 2020 01:42:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="wWRpRZlK"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=sartura-hr.20150623.gappssmtp.com header.i=@sartura-hr.20150623.gappssmtp.com header.b="XEEXKgLE" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CD85520C09 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=sartura.hr Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=/qBH+scH08hOE4YBPSrquuPCCP0ECcU9cXYAftrNR6o=; b=wWRpRZlKTledtQEfd2JVxOau0 EKYZQ1jS87vO5s2Xm8UxdTGUof6b5hlSsOrClHyhPxOwJXrDHtU0ps1fRA3IhhfItUrRmmNZDfwfT IcvHKlI3Go4bxSxcPDaAIYN/hZKLAoujAmHyGLAaf565TqNZrThgZAXEK6xiV/oTT0dI+6s6rf++3 3/LAvVGQ+5n5BHumxj1SAMb4+3cHFnZWUXFrZhwWLNz94Q5uYrJG+4TphHRbw+szlU3Xrit3XjIWL aBfhoXY2vClz2LukREZaL30CMMuV7XMIjeOQCSnG09YAHeOAOUR0H6p646jW+gCeTeZ3UWu8sSsDU 7aIP+oLig==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kNR80-0000Op-Jp; Wed, 30 Sep 2020 01:41:56 +0000 Received: from mail-ed1-x52a.google.com ([2a00:1450:4864:20::52a]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kNR7S-0000Eg-OD for linux-arm-kernel@lists.infradead.org; Wed, 30 Sep 2020 01:41:24 +0000 Received: by mail-ed1-x52a.google.com with SMTP id l17so69838edq.12 for ; Tue, 29 Sep 2020 18:41:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sartura-hr.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=jsG9e64+hm1kWvWLBkpftUqDmTbdR66JgHzNao/M1zI=; b=XEEXKgLEzoyoUtHuREj71CIn39LLDv55q1p4YoqZMbn50ipbK7SMbGwr/+8TwH0q7u eFBd8YaGql4DlTJVLHfs1EKHxVRKt5nKNj99CAVElXSwD1a8Bphj6Zu68cqMLv4AW8gx 6aPZRcaoTcjVftEDpEobqDIUxuxKundkv80ItaN6Ad8C9xazOcQMIjLtrz6rfitREvd3 gUwckuDq3g1ckHE419ZSpad5zaUA737Zv+MErgleOcFGfEArtAiE3u/CVcyabHoT+f31 849yusLJeNjiBZOUdwg0LIhFcBsKUlgrpwMgCnTH3pwAOQfWNfPp7IyYJiI8/j7ssdAS pBAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=jsG9e64+hm1kWvWLBkpftUqDmTbdR66JgHzNao/M1zI=; b=fhK858Jzl2bUL4x+YE0862ivMqQMeIYxwuafGpaOHM2f589h0Gx78PIgqq7Nw5Jo8O hMtBmiLuhh1kCh3Mr63sBylBNEE/8ngQb2P52FB4g96OymyPkd9Urpc40NubfqPDOcCz ZQySskYnb6tz/lQ4Fk7bZrSU1497eBNMIqHqpAdIaxAJbrbrjXnHIBBZ6pSLja9M8ebl 17VtPXdqc2X2qYuo6iu6GfRDp3gECqMeYqSlv0o4Nm+YfesQFzY5MiBj8rmIKsxRhhpE efwqE0P/7NbWKtDxZUGvbr7WeDSLx6sOGKt9ptgZWQF2IPwtlYTs0jLDZ53zjsZdqymM yk5w== X-Gm-Message-State: AOAM532IP+DXvvUhybpfiPMEWaayHa4bwMsb4WUfAvo5bcquYRUv25Vk FPPF8+kNPq2IcQKKvpLrtDyiug== X-Google-Smtp-Source: ABdhPJxfP7whcOzcrPG1GZ9fFLkvY16uwZqJCZ8/jhPqdeTwGOYnDOyL85QWrv8tFjQ1PACUsKwFuA== X-Received: by 2002:a05:6402:7d2:: with SMTP id u18mr290702edy.69.1601430081453; Tue, 29 Sep 2020 18:41:21 -0700 (PDT) Received: from localhost.localdomain ([2a00:ee2:4b0d:3000:290:faff:fe54:449c]) by smtp.gmail.com with ESMTPSA id q1sm203258ejy.37.2020.09.29.18.41.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Sep 2020 18:41:20 -0700 (PDT) From: Luka Kovacic To: linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-leds@vger.kernel.org Subject: [PATCH v3 5/7] Documentation/ABI: Add iei-wt61p803-puzzle driver sysfs interface documentation Date: Wed, 30 Sep 2020 03:40:56 +0200 Message-Id: <20200930014058.44460-6-luka.kovacic@sartura.hr> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200930014058.44460-1-luka.kovacic@sartura.hr> References: <20200930014058.44460-1-luka.kovacic@sartura.hr> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200929_214122_842580_8D746AD8 X-CRM114-Status: GOOD ( 15.23 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:52a listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: andrew@lunn.ch, jdelvare@suse.com, luka.perkov@sartura.hr, jason@lakedaemon.net, gregory.clement@bootlin.com, marek.behun@nic.cz, Luka Kovacic , robh+dt@kernel.org, dmurphy@ti.com, pavel@ucw.cz, robert.marko@sartura.hr, lee.jones@linaro.org, linux@roeck-us.net Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Add the iei-wt61p803-puzzle driver sysfs interface documentation to allow monitoring and control of the microcontroller from user space. Signed-off-by: Luka Kovacic Cc: Luka Perkov Cc: Robert Marko --- .../testing/sysfs-driver-iei-wt61p803-puzzle | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-driver-iei-wt61p803-puzzle diff --git a/Documentation/ABI/testing/sysfs-driver-iei-wt61p803-puzzle b/Documentation/ABI/testing/sysfs-driver-iei-wt61p803-puzzle new file mode 100644 index 000000000000..6e71d85f3296 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-iei-wt61p803-puzzle @@ -0,0 +1,55 @@ +What: /sys/bus/serial/devices/.../iei_wt61p803_puzzle_core/mac_address_* +Date: September 2020 +Contact: Luka Kovacic +Description: (RW) Internal factory assigned MAC address values + +What: /sys/bus/serial/devices/.../iei_wt61p803_puzzle_core/serial_number +Date: September 2020 +Contact: Luka Kovacic +Description: (RW) Internal factory assigned serial number + +What: /sys/bus/serial/devices/.../iei_wt61p803_puzzle_core/version +Date: September 2020 +Contact: Luka Kovacic +Description: (RO) Internal MCU firmware version + +What: /sys/bus/serial/devices/.../iei_wt61p803_puzzle_core/protocol_version +Date: September 2020 +Contact: Luka Kovacic +Description: (RO) Internal MCU communication protocol version + +What: /sys/bus/serial/devices/.../iei_wt61p803_puzzle_core/power_loss_recovery +Date: September 2020 +Contact: Luka Kovacic +Description: (RW) Host platform power loss recovery settings + Value mapping: 0 - Always-On, 1 - Always-Off, 2 - Always-AC, 3 - Always-WA + +What: /sys/bus/serial/devices/.../iei_wt61p803_puzzle_core/bootloader_mode +Date: September 2020 +Contact: Luka Kovacic +Description: (RO) Internal MCU bootloader mode status + +What: /sys/bus/serial/devices/.../iei_wt61p803_puzzle_core/power_status +Date: September 2020 +Contact: Luka Kovacic +Description: (RO) Power status indicates the host platform power on method. + Value mapping (bitwise list): + 0x80 - Null + 0x40 - Firmware flag + 0x20 - Power loss detection flag (powered off) + 0x10 - Power loss detection flag (AC mode) + 0x08 - Button power on + 0x04 - WOL power on + 0x02 - RTC alarm power on + 0x01 - AC recover power on + +What: /sys/bus/serial/devices/.../iei_wt61p803_puzzle_core/build_info +Date: September 2020 +Contact: Luka Kovacic +Description: (RO) Internal MCU firmware build date + Format: yyyy/mm/dd hh:mm + +What: /sys/bus/serial/devices/.../iei_wt61p803_puzzle_core/ac_recovery_status +Date: September 2020 +Contact: Luka Kovacic +Description: (RO) Host platform AC recovery status value From patchwork Wed Sep 30 01:40:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luka Kovacic X-Patchwork-Id: 11807559 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EFBF26CB for ; Wed, 30 Sep 2020 01:43:34 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A78F120738 for ; Wed, 30 Sep 2020 01:43:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="t6hdOvm6"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=sartura-hr.20150623.gappssmtp.com header.i=@sartura-hr.20150623.gappssmtp.com header.b="Eh/2MbHT" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A78F120738 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=sartura.hr Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=6oNOa+tZSwbBt7jm6GHZ3G7m6QFtllhP+axYnWkj3rw=; b=t6hdOvm68pCzB5eMU3pAmG0I3 Doa20O//QS2Iw6KXPnzVXmrNlqY19c5/76gE1bHgT11bwmA9udczxfr+F3EH0b1mJ+snyW+oW6Fsq 9v2fny/Q3rPhn93LyVKfpsV2QcD3Gh5LtEvD/DRkqLQNnAYTCLWGRCBXXI6tCy/dBPLMFNtrecH4j n7nyzcEYr3+cQBNbX6bH1g6NO9XztRCxpobfgPOfUDi3EaNO4eJpmiYOVSJ3v+sW/fXJoneJFAlCB JSSLS2fTD8RKI4TP6x0gWBROEjmSpLrecx+JvHFJqAB6Le2oiHHayWd6tIizZ5jNM0jDpidToq5pP pgiFvH4cQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kNR88-0000R9-4V; Wed, 30 Sep 2020 01:42:04 +0000 Received: from mail-ed1-x543.google.com ([2a00:1450:4864:20::543]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kNR7U-0000FO-5t for linux-arm-kernel@lists.infradead.org; Wed, 30 Sep 2020 01:41:25 +0000 Received: by mail-ed1-x543.google.com with SMTP id e22so94041edq.6 for ; Tue, 29 Sep 2020 18:41:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sartura-hr.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=j1nzLd4cVTawFtv7my0W6MRV0qtnqLD9Ylpuzx5aPFs=; b=Eh/2MbHTg7C7wg5J5iI7Jm2IbflWfNjmKw2xeKOYJfodnE3icMcftISphSs+qobhLM wimziWrIEDDRWj4xruXppexqqUCr3UBi5Nq+KVw/b/eEvgaSYmvaMel491DW9PVr101H l6azZspgCvVff8knC1YUeS8Df4uJvnfp5DwTMlx0O4ijou4NyY706Tf0UpU4QS5WOzUM cQEIFHMsJ7lROXn82YZudY867yjp8RRDIWi0uN1gY8Bd8MGwL6Dex1KlV4C7aTOawJfX 3DgsNKlwlf7HInWRD3tADsINgLzwy9b0qeFr4zTt7qFywQyQJs1cKWZsOml4baCveckX afNA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=j1nzLd4cVTawFtv7my0W6MRV0qtnqLD9Ylpuzx5aPFs=; b=D/IunlrTlU4qqec56B5sgjpiC4z3j0W87e+tb3+0a2zkfAQ+RTTqcwExgZj8eJBnZ+ I/HgTEWABUGoCWmXkqyL3kqz7L/oqn7LhUEtiLPpcA3/LozMB7+DBwvlgIm2XPs+obzb 8p5DwSEaVhqsRTh4Wijed7akDJTvybfika+E2bJZhvmvYizeyzLwJx2GqpUEtc8UhdT1 1kfNH2VpIF/FevGp7iwu8ZUnRnIet0vK7WwLJcDuLRV7eLuVokNyv2USZ94wax9ovDk7 GE5hoXB6Fgh9MCbmS7iui/l1GMRLW92hmjd75LRxOz3CSOI8zrCH9yxQZndrJuF9Z1xY sXKA== X-Gm-Message-State: AOAM530T41bVfkkRT7DK8XNr6O0gWqfT58bIFVAPGQT+jemuYB9L+rI0 TD5QsFUP5unKEFu8agHEIVsKAA== X-Google-Smtp-Source: ABdhPJyranPrEpXvW91gZlFSSM4AzTx8KUkqiJNG1xr+dWveWBsCKZud8F2QaxfpXVp11QFQOb4Klg== X-Received: by 2002:aa7:d144:: with SMTP id r4mr266149edo.303.1601430082966; Tue, 29 Sep 2020 18:41:22 -0700 (PDT) Received: from localhost.localdomain ([2a00:ee2:4b0d:3000:290:faff:fe54:449c]) by smtp.gmail.com with ESMTPSA id q1sm203258ejy.37.2020.09.29.18.41.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Sep 2020 18:41:22 -0700 (PDT) From: Luka Kovacic To: linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-leds@vger.kernel.org Subject: [PATCH v3 6/7] MAINTAINERS: Add an entry for the iEi WT61P803 PUZZLE driver Date: Wed, 30 Sep 2020 03:40:57 +0200 Message-Id: <20200930014058.44460-7-luka.kovacic@sartura.hr> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200930014058.44460-1-luka.kovacic@sartura.hr> References: <20200930014058.44460-1-luka.kovacic@sartura.hr> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200929_214124_253337_B9B985FF X-CRM114-Status: GOOD ( 11.54 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:543 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: andrew@lunn.ch, jdelvare@suse.com, luka.perkov@sartura.hr, jason@lakedaemon.net, gregory.clement@bootlin.com, marek.behun@nic.cz, Luka Kovacic , robh+dt@kernel.org, dmurphy@ti.com, pavel@ucw.cz, robert.marko@sartura.hr, lee.jones@linaro.org, linux@roeck-us.net Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Add an entry for the iEi WT61P803 PUZZLE driver (MFD, HWMON, LED drivers). Signed-off-by: Luka Kovacic Cc: Luka Perkov Cc: Robert Marko --- MAINTAINERS | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 190c7fa2ea01..0adf6cc499e5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8455,6 +8455,19 @@ F: include/net/nl802154.h F: net/ieee802154/ F: net/mac802154/ +IEI WT61P803 M801 MFD DRIVER +M: Luka Kovacic +L: linux-kernel@vger.kernel.org +S: Maintained +F: Documentation/ABI/stable/sysfs-driver-iei-wt61p803-puzzle +F: Documentation/devicetree/bindings/hwmon/iei,wt61p803-puzzle-hwmon.yaml +F: Documentation/devicetree/bindings/leds/iei,wt61p803-puzzle-leds.yaml +F: Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml +F: drivers/hwmon/iei-wt61p803-puzzle-hwmon.c +F: drivers/leds/leds-iei-wt61p803-puzzle.c +F: drivers/mfd/iei-wt61p803-puzzle.c +F: include/linux/mfd/iei-wt61p803-puzzle.h + IFE PROTOCOL M: Yotam Gigi M: Jamal Hadi Salim From patchwork Wed Sep 30 01:40:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luka Kovacic X-Patchwork-Id: 11807553 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0D1DF139F for ; Wed, 30 Sep 2020 01:42:39 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A8D7920738 for ; Wed, 30 Sep 2020 01:42:38 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="FV9yvEXA"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=sartura-hr.20150623.gappssmtp.com header.i=@sartura-hr.20150623.gappssmtp.com header.b="FHxnn4n9" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A8D7920738 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=sartura.hr Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=WHezjtLhK4fRpCQxyNkSUs0f11JhiKzUNJyXefeucDU=; b=FV9yvEXA9HVHXm0JqS3fFC0Ea vMBdqZlFyVfnWPtgxL5ITOROwUrEowQ1aEOAacSdPpT9i3REhQGdGiyidpGmrTY1tIJsSe1x1uEEB 2+hJbOJ2v8DlzoKDXaCI8DhkgfWfJ8PSXO3eIbTmc4M0GKf/LT3FRTUBf6Sf4v2f1unMW9T17PLG7 6/M1KduUVEdOLyoz7pZLImAPBCyEZeBzIKinpVEXAMcEag29RJbfMVxw0W1yVgwZ9YNrsTvuZhi54 r6lyTE9Gh6//2G8oO/YKkgmsKQbxz4JWxitPknnmztwOf67dAFgsjdPP7o7b/puWJ2bjLhgwkkuMi UP8Rlz/tw==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kNR8P-0000WI-11; Wed, 30 Sep 2020 01:42:21 +0000 Received: from mail-ed1-x541.google.com ([2a00:1450:4864:20::541]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kNR7W-0000GE-Tg for linux-arm-kernel@lists.infradead.org; Wed, 30 Sep 2020 01:41:29 +0000 Received: by mail-ed1-x541.google.com with SMTP id k14so115884edo.1 for ; Tue, 29 Sep 2020 18:41:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sartura-hr.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FpGXxlELV+ewvDuzbDCb+SCNgc3ZRqoM8ufBOOKONjE=; b=FHxnn4n9vt+7/VQio9nnzp+9dG9P1tPE1SR7ciWC0fHYeoRT+0/h4QeUJLZEsrIB6J BGrDEWldFH88qg9SPYiAP7it1HzcDrZbHXa9y1vdebtKi/IjAKBhk1ehvpZo2iGG71Sa xtfNymkwKJn60raXdHbAP/VTpLGOFCrCJEtQkWp+WBCiN4tho4wYrhUqkZ1JCWfidWLg +mOBuYwzzz7dMc/CsUA1or+ca8OLryuZvIBOdE5wV9uFluG9mVNopnKfK361ACKYjyo3 WmjUf/+PhjatllnbxRvEbSg2CeT3h5HgAkBsmYCRtQZZ9WXqxE1teNnfwrkEWbXpVJss bumg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=FpGXxlELV+ewvDuzbDCb+SCNgc3ZRqoM8ufBOOKONjE=; b=MR/zPEO7CAE55sc+sOhxRw3ZJXLQEb+4G04pSadoW5kVeGzGeUz0wsN9I0vHeFvb2Q MYPeExORxb19H5rkWnKw8a8orzBRaoIxVNScl1+posh7L2r6qZV3w7r/d3GjFmq655/b 6jZ0L2sPkl4ONMuH0bNDtMZ48jQH9q5bx0URnzrg+0mkWQVyUOPf7nRJY/Y/ugLtGiSM 5CdFlww/RocTBl30HBxhOC2sAlryUNKgOjkGSntBCHSoa1Wx7QfcdGR+mZ3bBl7K0m/S YdcTThZhc0Vhst/ar2dxy4CBPkSmLTr38r9WpY3mXgr5H8KZLxTVnGCVyg48VypHt9XD FQSA== X-Gm-Message-State: AOAM531KVP7oFf4u4I08fh83ZVvksYkwRrLDcGFthFLU99EUDnMCuvOf h+GKi5zERGZEk8TbFEOTGKtNVA== X-Google-Smtp-Source: ABdhPJwBo9zNzdbvtGkTeyJQ7qOb20GRTZQzXDBlpiGuokQTUsEuePxOWiq4vxdoGA6f/8w9szOn9A== X-Received: by 2002:a50:ed02:: with SMTP id j2mr296622eds.137.1601430084764; Tue, 29 Sep 2020 18:41:24 -0700 (PDT) Received: from localhost.localdomain ([2a00:ee2:4b0d:3000:290:faff:fe54:449c]) by smtp.gmail.com with ESMTPSA id q1sm203258ejy.37.2020.09.29.18.41.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Sep 2020 18:41:24 -0700 (PDT) From: Luka Kovacic To: linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-leds@vger.kernel.org Subject: [PATCH v3 7/7] arm64: dts: marvell: Add a device tree for the iEi Puzzle-M801 board Date: Wed, 30 Sep 2020 03:40:58 +0200 Message-Id: <20200930014058.44460-8-luka.kovacic@sartura.hr> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200930014058.44460-1-luka.kovacic@sartura.hr> References: <20200930014058.44460-1-luka.kovacic@sartura.hr> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200929_214126_999524_CF90242B X-CRM114-Status: GOOD ( 19.17 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:541 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: andrew@lunn.ch, jdelvare@suse.com, luka.perkov@sartura.hr, jason@lakedaemon.net, gregory.clement@bootlin.com, marek.behun@nic.cz, Luka Kovacic , robh+dt@kernel.org, dmurphy@ti.com, pavel@ucw.cz, robert.marko@sartura.hr, lee.jones@linaro.org, linux@roeck-us.net Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Add initial support for the iEi Puzzle-M801 1U Rackmount Network Appliance board. The board is based on the quad-core Marvell Armada 8040 SoC and supports up to 16 GB of DDR4 2400 MHz ECC RAM. It has a PCIe x16 slot (x2 lanes only) and an M.2 type B slot. Main system hardware: 2x USB 3.0 4x Gigabit Ethernet 2x SFP+ 1x SATA 3.0 1x M.2 type B 1x RJ45 UART 1x SPI flash 1x iEi WT61P803 PUZZLE Microcontroller 1x EPSON RX8010 RTC (used instead of the integrated Marvell RTC controller) 6x SFP+ LED 1x HDD LED All of the hardware listed above is supported and tested in this port. Signed-off-by: Luka Kovacic Acked-by: Andrew Lunn Cc: Luka Perkov Cc: Robert Marko --- arch/arm64/boot/dts/marvell/Makefile | 1 + .../dts/marvell/armada-8040-puzzle-m801.dts | 524 ++++++++++++++++++ 2 files changed, 525 insertions(+) create mode 100644 arch/arm64/boot/dts/marvell/armada-8040-puzzle-m801.dts diff --git a/arch/arm64/boot/dts/marvell/Makefile b/arch/arm64/boot/dts/marvell/Makefile index 3e5f2e7a040c..e413c3261792 100644 --- a/arch/arm64/boot/dts/marvell/Makefile +++ b/arch/arm64/boot/dts/marvell/Makefile @@ -12,6 +12,7 @@ dtb-$(CONFIG_ARCH_MVEBU) += armada-8040-clearfog-gt-8k.dtb dtb-$(CONFIG_ARCH_MVEBU) += armada-8040-db.dtb dtb-$(CONFIG_ARCH_MVEBU) += armada-8040-mcbin.dtb dtb-$(CONFIG_ARCH_MVEBU) += armada-8040-mcbin-singleshot.dtb +dtb-$(CONFIG_ARCH_MVEBU) += armada-8040-puzzle-m801.dtb dtb-$(CONFIG_ARCH_MVEBU) += armada-8080-db.dtb dtb-$(CONFIG_ARCH_MVEBU) += cn9130-db.dtb dtb-$(CONFIG_ARCH_MVEBU) += cn9131-db.dtb diff --git a/arch/arm64/boot/dts/marvell/armada-8040-puzzle-m801.dts b/arch/arm64/boot/dts/marvell/armada-8040-puzzle-m801.dts new file mode 100644 index 000000000000..f1dd09ed22e9 --- /dev/null +++ b/arch/arm64/boot/dts/marvell/armada-8040-puzzle-m801.dts @@ -0,0 +1,524 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2016 Marvell Technology Group Ltd. + * Copyright (C) 2020 Sartura Ltd. + * + * Device Tree file for iEi Puzzle-M801 + */ + +#include "armada-8040.dtsi" + +#include +#include + +/ { + model = "iEi-Puzzle-M801"; + compatible = "marvell,armada8040", "marvell,armada-ap806-quad", "marvell,armada-ap806"; + + aliases { + ethernet0 = &cp0_eth0; + ethernet1 = &cp1_eth0; + ethernet2 = &cp0_eth1; + ethernet3 = &cp0_eth2; + ethernet4 = &cp1_eth1; + ethernet5 = &cp1_eth2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; + + /* Regulator labels correspond with schematics */ + v_3_3: regulator-3-3v { + compatible = "regulator-fixed"; + regulator-name = "v_3_3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + status = "okay"; + }; + + v_5v0_usb3_hst_vbus: regulator-usb3-vbus0 { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&cp0_gpio2 15 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_xhci_vbus_pins>; + regulator-name = "v_5v0_usb3_hst_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + status = "okay"; + }; + + v_vddo_h: regulator-1-8v { + compatible = "regulator-fixed"; + regulator-name = "v_vddo_h"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + status = "okay"; + }; + + sfp_cp0_eth0: sfp-cp0-eth0 { + compatible = "sff,sfp"; + i2c-bus = <&sfpplus0_i2c>; + los-gpio = <&sfpplus_gpio 11 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&sfpplus_gpio 10 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&sfpplus_gpio 9 GPIO_ACTIVE_HIGH>; + tx-fault-gpio = <&sfpplus_gpio 8 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <3000>; + }; + + sfp_cp1_eth0: sfp-cp1-eth0 { + compatible = "sff,sfp"; + i2c-bus = <&sfpplus1_i2c>; + los-gpio = <&sfpplus_gpio 3 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&sfpplus_gpio 2 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&sfpplus_gpio 1 GPIO_ACTIVE_HIGH>; + tx-fault-gpio = <&sfpplus_gpio 0 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <3000>; + }; + + leds { + compatible = "gpio-leds"; + status = "okay"; + pinctrl-0 = <&cp0_sfpplus_led_pins &cp1_sfpplus_led_pins>; + pinctrl-names = "default"; + + led-0 { + /* SFP+ port 2: Activity */ + function = LED_FUNCTION_LAN; + function-enumerator = <0>; + gpios = <&cp1_gpio1 6 GPIO_ACTIVE_LOW>; + }; + + led-1 { + /* SFP+ port 1: Activity */ + function = LED_FUNCTION_LAN; + function-enumerator = <1>; + gpios = <&cp1_gpio1 14 GPIO_ACTIVE_LOW>; + }; + + led-2 { + /* SFP+ port 2: 10 Gbps indicator */ + function = LED_FUNCTION_LAN; + function-enumerator = <2>; + gpios = <&cp1_gpio1 7 GPIO_ACTIVE_LOW>; + }; + + led-3 { + /* SFP+ port 2: 1 Gbps indicator */ + function = LED_FUNCTION_LAN; + function-enumerator = <3>; + gpios = <&cp1_gpio1 8 GPIO_ACTIVE_LOW>; + }; + + led-4 { + /* SFP+ port 1: 10 Gbps indicator */ + function = LED_FUNCTION_LAN; + function-enumerator = <4>; + gpios = <&cp1_gpio1 10 GPIO_ACTIVE_LOW>; + }; + + led-5 { + /* SFP+ port 1: 1 Gbps indicator */ + function = LED_FUNCTION_LAN; + function-enumerator = <5>; + gpios = <&cp1_gpio1 31 GPIO_ACTIVE_LOW>; + }; + + led-6 { + function = LED_FUNCTION_DISK; + linux,default-trigger = "disk-activity"; + gpios = <&cp0_gpio2 22 GPIO_ACTIVE_HIGH>; + }; + + }; +}; + +&ap_sdhci0 { + bus-width = <8>; + /* + * Not stable in HS modes - phy needs "more calibration", so add + * the "slow-mode" and disable SDR104, SDR50 and DDR50 modes. + */ + marvell,xenon-phy-slow-mode; + no-1-8-v; + no-sd; + no-sdio; + non-removable; + status = "okay"; + vqmmc-supply = <&v_vddo_h>; +}; + +&ap_thermal_cpu1 { + trips { + cpu_active: cpu-active { + temperature = <44000>; + hysteresis = <2000>; + type = "active"; + }; + }; + cooling-maps { + fan-map { + trip = <&cpu_active>; + cooling-device = <&chassis_fan_group0 64 THERMAL_NO_LIMIT>, + <&chassis_fan_group1 64 THERMAL_NO_LIMIT>; + }; + }; +}; + +&i2c0 { + clock-frequency = <100000>; + status = "okay"; + + rtc@32 { + compatible = "epson,rx8010"; + reg = <0x32>; + }; +}; + +&spi0 { + status = "okay"; + spi-flash@0 { + #address-cells = <0x1>; + #size-cells = <0x1>; + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-max-frequency = <20000000>; + partition@u-boot { + label = "u-boot"; + reg = <0x00000000 0x001f0000>; + }; + partition@u-boot-env { + label = "u-boot-env"; + reg = <0x001f0000 0x00010000>; + }; + partition@ubi1 { + label = "ubi1"; + reg = <0x00200000 0x03f00000>; + }; + partition@ubi2 { + label = "ubi2"; + reg = <0x04100000 0x03f00000>; + }; + }; +}; + +&uart0 { + status = "okay"; + pinctrl-0 = <&uart0_pins>; + pinctrl-names = "default"; +}; + +&uart1 { + status = "okay"; + /* iEi WT61P803 PUZZLE MCU Controller */ + mcu { + compatible = "iei,wt61p803-puzzle"; + current-speed = <115200>; + enable-beep; + + leds { + compatible = "iei,wt61p803-puzzle-leds"; + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + function = LED_FUNCTION_POWER; + color = ; + }; + }; + + iei-wt61p803-puzzle-hwmon { + compatible = "iei,wt61p803-puzzle-hwmon"; + + #address-cells = <1>; + #size-cells = <0>; + + chassis_fan_group0:fan-group@0 { + #cooling-cells = <2>; + reg = <0x00>; + cooling-levels = <64 102 170 230 250>; + }; + + chassis_fan_group1:fan-group@1 { + #cooling-cells = <2>; + reg = <0x01>; + cooling-levels = <64 102 170 230 250>; + }; + }; + }; +}; + +&cp0_rtc { + status = "disabled"; +}; + +&cp0_i2c0 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_i2c0_pins>; + status = "okay"; + + sfpplus_gpio: gpio@21 { + compatible = "nxp,pca9555"; + reg = <0x21>; + gpio-controller; + #gpio-cells = <2>; + }; + + eeprom@54 { + compatible = "atmel,24c04"; + reg = <0x54>; + }; +}; + +&cp0_i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_i2c1_pins>; + status = "okay"; + + i2c-switch@70 { + compatible = "nxp,pca9544"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x70>; + + sfpplus0_i2c: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + + sfpplus1_i2c: i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + }; + }; +}; + +&cp0_uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&cp0_uart1_pins>; + status = "okay"; +}; + +&cp0_mdio { + #address-cells = <1>; + #size-cells = <0>; + + status = "okay"; + + ge_phy2: ethernet-phy@0 { + reg = <0>; + }; + + ge_phy3: ethernet-phy@1 { + reg = <1>; + }; +}; + +&cp0_pcie0 { + pinctrl-names = "default"; + pinctrl-0 = <&cp0_pcie_pins>; + num-lanes = <1>; + num-viewport = <8>; + reset-gpios = <&cp0_gpio2 20 GPIO_ACTIVE_LOW>; + ranges = <0x82000000 0x0 0xc0000000 0x0 0xc0000000 0x0 0x20000000>; + phys = <&cp0_comphy0 0>; + phy-names = "cp0-pcie0-x1-phy"; + status = "okay"; +}; + +&cp0_pinctrl { + cp0_ge_mdio_pins: ge-mdio-pins { + marvell,pins = "mpp32", "mpp34"; + marvell,function = "ge"; + }; + cp0_i2c1_pins: i2c1-pins { + marvell,pins = "mpp35", "mpp36"; + marvell,function = "i2c1"; + }; + cp0_i2c0_pins: i2c0-pins { + marvell,pins = "mpp37", "mpp38"; + marvell,function = "i2c0"; + }; + cp0_uart1_pins: uart1-pins { + marvell,pins = "mpp40", "mpp41"; + marvell,function = "uart1"; + }; + cp0_xhci_vbus_pins: xhci0-vbus-pins { + marvell,pins = "mpp47"; + marvell,function = "gpio"; + }; + cp0_pcie_pins: pcie-pins { + marvell,pins = "mpp52"; + marvell,function = "gpio"; + }; + cp0_sdhci_pins: sdhci-pins { + marvell,pins = "mpp55", "mpp56", "mpp57", "mpp58", "mpp59", + "mpp60", "mpp61"; + marvell,function = "sdio"; + }; + cp0_sfpplus_led_pins: sfpplus-led-pins { + marvell,pins = "mpp54"; + marvell,function = "gpio"; + }; +}; + +&cp0_ethernet { + status = "okay"; +}; + +&cp0_eth0 { + status = "okay"; + phy-mode = "10gbase-r"; + phys = <&cp0_comphy4 0>; + local-mac-address = [ae 00 00 00 ff 00]; + sfp = <&sfp_cp0_eth0>; + managed = "in-band-status"; +}; + +&cp0_eth1 { + status = "okay"; + phy = <&ge_phy2>; + phy-mode = "sgmii"; + local-mac-address = [ae 00 00 00 ff 01]; + phys = <&cp0_comphy3 1>; +}; + +&cp0_eth2 { + status = "okay"; + phy-mode = "sgmii"; + phys = <&cp0_comphy1 2>; + local-mac-address = [ae 00 00 00 ff 02]; + phy = <&ge_phy3>; +}; + +&cp0_sata0 { + status = "okay"; + + sata-port@0 { + phys = <&cp0_comphy2 0>; + phy-names = "cp0-sata0-0-phy"; + }; + + sata-port@1 { + phys = <&cp0_comphy5 1>; + phy-names = "cp0-sata0-1-phy"; + }; +}; + +&cp0_sdhci0 { + broken-cd; + bus-width = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_sdhci_pins>; + status = "okay"; + vqmmc-supply = <&v_3_3>; +}; + +&cp0_usb3_0 { + status = "okay"; +}; + +&cp0_usb3_1 { + status = "okay"; +}; + +&cp1_i2c0 { + clock-frequency = <100000>; + status = "disabled"; +}; + +&cp1_i2c1 { + clock-frequency = <100000>; + status = "disabled"; +}; + +&cp1_rtc { + status = "disabled"; +}; + +&cp1_ethernet { + status = "okay"; +}; + +&cp1_eth0 { + status = "okay"; + phy-mode = "10gbase-r"; + phys = <&cp1_comphy4 0>; + local-mac-address = [ae 00 00 00 ff 03]; + sfp = <&sfp_cp1_eth0>; + managed = "in-band-status"; +}; + +&cp1_eth1 { + status = "okay"; + phy = <&ge_phy4>; + phy-mode = "sgmii"; + local-mac-address = [ae 00 00 00 ff 04]; + phys = <&cp1_comphy3 1>; +}; + +&cp1_eth2 { + status = "okay"; + phy-mode = "sgmii"; + local-mac-address = [ae 00 00 00 ff 05]; + phys = <&cp1_comphy5 2>; + phy = <&ge_phy5>; +}; + +&cp1_pinctrl { + cp1_sfpplus_led_pins: sfpplus-led-pins { + marvell,pins = "mpp6", "mpp7", "mpp8", "mpp10", "mpp14", "mpp31"; + marvell,function = "gpio"; + }; +}; + +&cp1_uart0 { + status = "disabled"; +}; + +&cp1_comphy2 { + cp1_usbh0_con: connector { + compatible = "usb-a-connector"; + phy-supply = <&v_5v0_usb3_hst_vbus>; + }; +}; + +&cp1_usb3_0 { + phys = <&cp1_comphy2 0>; + phy-names = "cp1-usb3h0-comphy"; + status = "okay"; +}; + +&cp1_mdio { + #address-cells = <1>; + #size-cells = <0>; + + status = "okay"; + + ge_phy4: ethernet-phy@1 { + reg = <1>; + }; + ge_phy5: ethernet-phy@0 { + reg = <0>; + }; +}; + +&cp1_pcie0 { + num-lanes = <2>; + phys = <&cp1_comphy0 0>, <&cp1_comphy1 0>; + phy-names = "cp1-pcie0-x2-lane0-phy", "cp1-pcie0-x2-lane1-phy"; + status = "okay"; +};