From patchwork Tue Apr 15 14:49:17 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= X-Patchwork-Id: 881491 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B53701B0434; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728559; cv=none; b=siZzUVw5rFIj6XBoB9Sep8tbzSEOo8MruypfsFjf8Z5gI+RML0zySrtn1UbExwd789UiD/vhAEZt1zKEa+xjGr213Oy5xMmuwhJME1Xe9LSZ1FIzuI97sXtR85IS0AQfCYX2QPZ8X/jR+qUVs/MmVseVMDKGAUDd4rJXEqrtqQw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728559; c=relaxed/simple; bh=t+MFC0OOW7FL9P3NBvk9YJB1PRIqCHoW3sBDq9L3ph4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=N9xUp8EZSheFCqeHbyptTx+GyHl9I+/O7UBVzWXrm54mat6+YaNhMOMEkZbNBa2neHjc7d4RhrBrPZODjL94J/hc8JtsxXWNphyLQcwN+r9iroMgFEX1AcVdBrpwJvwfysNWjGgTLKZkXfs82sRUJcDrWm6JgOiyVUAm8FjHFPA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XGBxZ9z3; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="XGBxZ9z3" Received: by smtp.kernel.org (Postfix) with ESMTPS id 340E5C4CEED; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744728559; bh=t+MFC0OOW7FL9P3NBvk9YJB1PRIqCHoW3sBDq9L3ph4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=XGBxZ9z3xXNwqTeXiO339vy9J3qyhWE+lqTVjKpfzQYUzY03RiVoMvRPOaMjr7c0d 6TX2+req5MKJFoa11WDATCp/hBEndaMg/x/k2qFY34VVK8hrtlwbHC+WDrfSsUAYz5 qBsKVxcPupcMvPUd+gAJWFATi2cmpN/iCYZAWi9K/cSr5JIoCIs1Hgs+WU9fs2Eqja vBv8x8QImvGDOq3JkC2Q5G8DEppHwzzC62pTylEOF4COEDISYAW2AKryK/dNd7undZ ELfSI+h2j0ZOzKKxLwtvWwPUUtKUbqrruoWZzTdA6pIZn9o+3lRntYW5aNq4C2Mlh9 rBmqDqy+aVDSQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 262F0C369B8; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Tue, 15 Apr 2025 15:49:17 +0100 Subject: [PATCH v2 01/17] dt-bindings: mfd: adp5585: ease on the required properties Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250415-dev-adp5589-fw-v2-1-3a799c3ed812@analog.com> References: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> In-Reply-To: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> To: linux-gpio@vger.kernel.org, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-input@vger.kernel.org Cc: Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Linus Walleij , Bartosz Golaszewski , Dmitry Torokhov , Laurent Pinchart , Liu Ying X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1744728559; l=940; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=/k0WMsS4BWsTpP8Xx6eyHKSypU/ajvWKXfPISoK6ADU=; b=5rQS/8anAWBkFi99wDH783dhTAdGT/yvGR5RdywD0rSufCQ56NKmImnw1uPKEvZerGW4IcSak sZfqwfNZ+ggDVi+TAxCexIrMjM4GIm68YotXCsQqD5WU44zd+9/nNJP X-Developer-Key: i=nuno.sa@analog.com; a=ed25519; pk=3NQwYA013OUYZsmDFBf8rmyyr5iQlxV/9H4/Df83o1E= X-Endpoint-Received: by B4 Relay for nuno.sa@analog.com/20231116 with auth_id=100 X-Original-From: =?utf-8?q?Nuno_S=C3=A1?= Reply-To: nuno.sa@analog.com From: Nuno Sá It is not mandatory to use all the capabilities of the device. One can very well only use it as a gpio controller without the PWM support. This will be even more evident when support for the matrix keymap is added. Hence drop the requirements for PWM and GPIO. Signed-off-by: Nuno Sá --- Documentation/devicetree/bindings/mfd/adi,adp5585.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml b/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml index ee2272f754a339569c793102928ddd13249f8fee..e30e22f964f78519b2ec207e9415e4897db5c702 100644 --- a/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml +++ b/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml @@ -52,9 +52,6 @@ patternProperties: required: - compatible - reg - - gpio-controller - - "#gpio-cells" - - "#pwm-cells" allOf: - if: From patchwork Tue Apr 15 14:49:18 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= X-Patchwork-Id: 881490 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B541E20ADD6; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728559; cv=none; b=IybJ7tBr6NklUKueWdDRKOEiXnEkpDpo+9r0OdEwFoVh0vhG7J1RsoeeclZcjgZQhiaFVv2/eshZclo7KFwh9ERnVI3ExTZ82mQmLjLI9n+k5R8gDBhPq0MFpnWWdDi/a69PHg5xc5dNZPP3OpaHuvLFvMrALEtb1NchfQLNcI8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728559; c=relaxed/simple; bh=tCLUDJBBZRusjFbUccJ5PsocSRcXrEt0fYuxnj8grt8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=I/gp1cS5RiaP2oUxUHYS+HLZEX4PV5/l/6aIejgOSi3yH1ZRAmd6ZasUaD15LL+coc5Rci/ZYuzj2UqIxUWwjcn78kgB0zHoX34GY0GyZ1GpW5CEoQgxGXTxxzlk/NfQ8/iAe2W0n5m4pEJlWA+7xklsoV81WXi1uiqtnDduQeI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NAgHKZkA; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NAgHKZkA" Received: by smtp.kernel.org (Postfix) with ESMTPS id 3EFACC4CEEC; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744728559; bh=tCLUDJBBZRusjFbUccJ5PsocSRcXrEt0fYuxnj8grt8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=NAgHKZkAgSruq8a51WFVTChJECVZMWmuvOTsb3wzadDhdHhdr+a4ZwUEZ9SSp2S/e c8v5YpNyk/DvY8+0VFSdqxiSua/EzGU61FalPQCYjSjfrnvFC8+xf8feLjz0Liy3Ql xtu6h+qxqHFnR7u4vreSVpFb/LjqHLwScmupv8hEFptslHJvEqjmxhDcdftqBr9xds rN+smtKYUGdq1YAXr6n/+Or1mt80qqgiK9r56TT69zywA9/GTEPrA6CjFeDxgkzIzh MCAEOfHC0jWvE6CzZIR+RqiRMx5FSeETywNtQxFwY+Tq23SnvTvv2safCdv6sym3RU hzSKjOpUTuSWg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3349AC369BD; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Tue, 15 Apr 2025 15:49:18 +0100 Subject: [PATCH v2 02/17] mfd: adp5585: enable oscilator during probe Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250415-dev-adp5589-fw-v2-2-3a799c3ed812@analog.com> References: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> In-Reply-To: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> To: linux-gpio@vger.kernel.org, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-input@vger.kernel.org Cc: Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Linus Walleij , Bartosz Golaszewski , Dmitry Torokhov , Laurent Pinchart , Liu Ying X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1744728559; l=1542; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=0tQ31SANYeFcAJsuV7bmOjiF8K0Yi3KIUJPgQunhZHU=; b=tQSR/7XDPiNbDTOb4PirNnhZGuBdhopkN3+ooPCV7NZP2blgafm65gjRHSzfGNSwhlOQdtXiI cXY8GnPGl8KC6ndrUwgrjkNcyn1EdjaT9mAIUOEnlNdDPhCrZiWc9Jh X-Developer-Key: i=nuno.sa@analog.com; a=ed25519; pk=3NQwYA013OUYZsmDFBf8rmyyr5iQlxV/9H4/Df83o1E= X-Endpoint-Received: by B4 Relay for nuno.sa@analog.com/20231116 with auth_id=100 X-Original-From: =?utf-8?q?Nuno_S=C3=A1?= Reply-To: nuno.sa@analog.com From: Nuno Sá Make sure to enable the oscillator in the top device. This will allow to not control this in the child PWM device as that would not work with future support for keyboard matrix where the oscillator needs to be always enabled (and so cannot be disabled by disabling PWM). Signed-off-by: Nuno Sá --- drivers/mfd/adp5585.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/mfd/adp5585.c b/drivers/mfd/adp5585.c index 160e0b38106a6d78f7d4b7c866cb603d96ea673e..f17b5f2474cac6a403556694066f438288264a49 100644 --- a/drivers/mfd/adp5585.c +++ b/drivers/mfd/adp5585.c @@ -110,6 +110,13 @@ static const struct regmap_config adp5585_regmap_configs[] = { }, }; +static void adp5585_osc_disable(void *data) +{ + const struct adp5585_dev *adp5585 = data; + + regmap_write(adp5585->regmap, ADP5585_GENERAL_CFG, 0); +} + static int adp5585_i2c_probe(struct i2c_client *i2c) { const struct regmap_config *regmap_config; @@ -138,6 +145,15 @@ static int adp5585_i2c_probe(struct i2c_client *i2c) return dev_err_probe(&i2c->dev, -ENODEV, "Invalid device ID 0x%02x\n", id); + ret = regmap_set_bits(adp5585->regmap, ADP5585_GENERAL_CFG, + ADP5585_OSC_EN); + if (ret) + return ret; + + ret = devm_add_action_or_reset(&i2c->dev, adp5585_osc_disable, adp5585); + if (ret) + return ret; + ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO, adp5585_devs, ARRAY_SIZE(adp5585_devs), NULL, 0, NULL); From patchwork Tue Apr 15 14:49:21 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= X-Patchwork-Id: 881487 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4145229B76C; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728560; cv=none; b=LCQ/DkZ5WreZs+tRP5hIdOo3yA/S0U9WLccrz3AqbAxywq9iZ4mjZq1AykD2O3uiciwHqzilIF2ApkybuaXoAVgi2ozoAq0Un2RPu9iHGLLPbdXwJj+fYCuB6KzcYyd1fVkh0iZY0/WLSpDp+JNm9AzPON+P0iAm79DuirZJ3fY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728560; c=relaxed/simple; bh=wTREZxYBrpJ9iX8vTdiRkhUcGSZDxA0IGE7Af2VCpxA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VJq8MFepdo/YnWjZ99JlelrhwYbHZnNWInNOpFgz0l7kTWlw6I9NJqn9w1ZepdwVLT+m9IFRLW+0xlcprbxU1IXnlXXybmkT9BxbmqdVTUrz4A5j2GobTF5rKCClvkC4og/s9rtXirxV6rssVGO30dWsSwJgT+U+Ab+i9dEMcFQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JDkepYxa; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="JDkepYxa" Received: by smtp.kernel.org (Postfix) with ESMTPS id 6FBB4C4CEF6; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744728559; bh=wTREZxYBrpJ9iX8vTdiRkhUcGSZDxA0IGE7Af2VCpxA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=JDkepYxa/gPxgqI/XiQAoDJCPsBz0bbzeYHPIBMMzb6PbsnywPmOrrFlpzNDYsVcc hYrqPIT60h5TkM/dV2HVdQ6m4TCCqRyA0FJ6JxatGtOFtE7FUvyhPOTRNuzYB9bLAR Zlfil1HlW79XOToLnl8OFWdk9pz/tUOY+GXX3y+LnAJWcMlZsnto0UQtXvii5FJcZg jNAJe/eTbI4bC1aA9FNY1Et0v5rJvNNUBgDLNoS3kg0E9lRn4S7CrUKxo5TEP50lMC jgwk/+errEvHlohqLKZEvoCyl0s1RQyttf24UChIV0ad9rpPaNHVqvdN6+IZ6DgeEf 5kNlt5efB8bug== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 657C0C369B8; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Tue, 15 Apr 2025 15:49:21 +0100 Subject: [PATCH v2 05/17] dt-bindings: mfd: adp5585: document adp5589 I/O expander Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250415-dev-adp5589-fw-v2-5-3a799c3ed812@analog.com> References: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> In-Reply-To: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> To: linux-gpio@vger.kernel.org, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-input@vger.kernel.org Cc: Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Linus Walleij , Bartosz Golaszewski , Dmitry Torokhov , Laurent Pinchart , Liu Ying X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1744728559; l=3566; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=YoojjYm1UzSm+sJS5QEfKj93KLVCY30qFWFJCm6+f8k=; b=gk/mSBZfpRljrZwQ0LifFheXBkqUVdMVvY1fVhids2wWUJWdVfVNJ+JLACxIXwJQ4R6zBu/AE yIpFaL3dS3PCIs0PQT0aRQ6CltFZcmbmck6zKkSlA0cZ8WlFamnkOv4 X-Developer-Key: i=nuno.sa@analog.com; a=ed25519; pk=3NQwYA013OUYZsmDFBf8rmyyr5iQlxV/9H4/Df83o1E= X-Endpoint-Received: by B4 Relay for nuno.sa@analog.com/20231116 with auth_id=100 X-Original-From: =?utf-8?q?Nuno_S=C3=A1?= Reply-To: nuno.sa@analog.com From: Nuno Sá The ADP5589 is a 19 I/O port expander with built-in keypad matrix decoder, programmable logic, reset generator, and PWM generator. We can't really have adp5589 devices fallback to adp5585 (which have less pins) because there are some significant differences in the register map. Signed-off-by: Nuno Sá --- .../devicetree/bindings/mfd/adi,adp5585.yaml | 47 +++++++++++++++++----- .../devicetree/bindings/trivial-devices.yaml | 2 - 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml b/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml index e30e22f964f78519b2ec207e9415e4897db5c702..d690a411b3a4307f6dd5f4a432a357e89fefabb0 100644 --- a/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml +++ b/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml @@ -15,14 +15,21 @@ description: properties: compatible: - items: - - enum: - - adi,adp5585-00 # Default - - adi,adp5585-01 # 11 GPIOs - - adi,adp5585-02 # No pull-up resistors by default on special pins - - adi,adp5585-03 # Alternate I2C address - - adi,adp5585-04 # Pull-down resistors on all pins by default - - const: adi,adp5585 + oneOf: + - items: + - enum: + - adi,adp5585-00 # Default + - adi,adp5585-01 # 11 GPIOs + - adi,adp5585-02 # No pull-up resistors by default on special pins + - adi,adp5585-03 # Alternate I2C address + - adi,adp5585-04 # Pull-down resistors on all pins by default + - const: adi,adp5585 + - items: + - enum: + - adi,adp5589-00 # Default + - adi,adp5589-01 # R4 defaulted to RESET1 output + - adi,adp5589-02 # Pull-down resistors by default on special pins + - const: adi,adp5589 reg: maxItems: 1 @@ -62,7 +69,17 @@ allOf: then: properties: gpio-reserved-ranges: false - else: + + - if: + properties: + compatible: + contains: + enum: + - adi,adp5585-00 + - adi,adp5585-03 + - adi,adp5585-04 + - adi,adp5585-02 + then: properties: gpio-reserved-ranges: maxItems: 1 @@ -71,6 +88,18 @@ allOf: - const: 5 - const: 1 + - if: + properties: + compatible: + contains: + enum: + - adi,adp5589-00 + - adi,adp5589-01 + - adi,adp5589-02 + then: + properties: + gpio-reserved-ranges: false + additionalProperties: false examples: diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml index 8da408107e55483affedb7e697eb79e8c8902ed9..208fe4242672d9da66799c2742a9381938737232 100644 --- a/Documentation/devicetree/bindings/trivial-devices.yaml +++ b/Documentation/devicetree/bindings/trivial-devices.yaml @@ -39,8 +39,6 @@ properties: - ad,adm9240 # AD5110 - Nonvolatile Digital Potentiometer - adi,ad5110 - # Analog Devices ADP5589 Keypad Decoder and I/O Expansion - - adi,adp5589 # Analog Devices LT7182S Dual Channel 6A, 20V PolyPhase Step-Down Silent Switcher - adi,lt7182s # AMS iAQ-Core VOC Sensor From patchwork Tue Apr 15 14:49:22 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= X-Patchwork-Id: 881489 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EC2A929A3C9; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728560; cv=none; b=T9RlzrL/9gE5v6AbvkgpjKnZVlIX6BWvIw6jw9TP22sZ+prYPR+Hl3qOertTJDF/mN0SFwskJrLcO+w13M8IBU0f2sthqsax0kC19aKHacU2v2tG7MPr7SgkXHjem5+8RvLyfUl13+12VKmXehyybwbn7HIhEwqjkMrdAljokqQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728560; c=relaxed/simple; bh=6LUcU1cSxfaPq2phxCFm36dqYIRfxTm/+zFai44GhJo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=BLMWshepp8QoI+9y4s27BYbxwqJd+ddHKup1U0pCmsn+cZnUwV4yyoLU0TiDzgeWYaTFDSvNq4qKfal/HzUjUsndP8D2TcYERtvWrH+X/uxdZPVe8pC8oOJHaZoDfaUojCnJ+qUGe0ziQJOzz65lX9uioL+IGkcCkuDXKWa8cnU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=M7vRK3Pz; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="M7vRK3Pz" Received: by smtp.kernel.org (Postfix) with ESMTPS id 83E18C4CEFB; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744728559; bh=6LUcU1cSxfaPq2phxCFm36dqYIRfxTm/+zFai44GhJo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=M7vRK3PzjN9B+8m+IYJm7VCePcM7U7sEyTtrfPIDmjMGaX79MrxNVJFydy95IhAOK J8I0eRaDs2aiCEg3kU63HNCV3NLxqq3/twV7zdtnRQNZS/T5jMpkxf5EYDHfNen2/y zPVYhTUobGZYtG8wKORApazFKOrYarA//auLoNh6Js3qJnK1gVaX6ElrxLQLW07mqL CYamRYeSt4cwf9+GGUOHVPSVShHhJl7gEcyEn18M3dbaWr3JJkyfoCR+EqYawOX06Q ApFrmhNm4DakNvBeaswavOZrrBEeNAUvxDwS4dmoHoeDVF50CmDZ6ltfKEiYy65BUg /4OU8zWQJUtOQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7840CC369BE; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Tue, 15 Apr 2025 15:49:22 +0100 Subject: [PATCH v2 06/17] mfd: adp5585: add support for adp5589 Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250415-dev-adp5589-fw-v2-6-3a799c3ed812@analog.com> References: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> In-Reply-To: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> To: linux-gpio@vger.kernel.org, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-input@vger.kernel.org Cc: Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Linus Walleij , Bartosz Golaszewski , Dmitry Torokhov , Laurent Pinchart , Liu Ying X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1744728560; l=13843; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=PGrku306Wdi2DTittwBpw2XDw32J03LAWrRR51MpVgg=; b=8pvFvZkOD1d6zkAU7BLJCSWdXh5iKocYrZM/Sx8ustkburz+E8AnyL9UPf6juOlWHjxjsVL0F FMCjBtX2L5tBKVt8M3A4LfxuMpH2iKGMd8uqUICqmQzGkGF5ld7urNB X-Developer-Key: i=nuno.sa@analog.com; a=ed25519; pk=3NQwYA013OUYZsmDFBf8rmyyr5iQlxV/9H4/Df83o1E= X-Endpoint-Received: by B4 Relay for nuno.sa@analog.com/20231116 with auth_id=100 X-Original-From: =?utf-8?q?Nuno_S=C3=A1?= Reply-To: nuno.sa@analog.com From: Nuno Sá The ADP5589 is a 19 I/O port expander with built-in keypad matrix decoder, programmable logic, reset generator, and PWM generator. This patch adds the foundation to add support for the adp5589 gpio and pwm drivers. Most importantly, we need to differentiate between some registers addresses. It also hints to future keymap support. Signed-off-by: Nuno Sá --- drivers/mfd/adp5585.c | 223 +++++++++++++++++++++++++++++++++++++++++--- include/linux/mfd/adp5585.h | 57 ++++++++++- 2 files changed, 268 insertions(+), 12 deletions(-) diff --git a/drivers/mfd/adp5585.c b/drivers/mfd/adp5585.c index fafe3ad93ea196e1eb8e79fecba58f36f12167eb..c3586c0d6aa2e7e7d94667993410610be7fc3672 100644 --- a/drivers/mfd/adp5585.c +++ b/drivers/mfd/adp5585.c @@ -25,6 +25,13 @@ static const struct mfd_cell adp5585_devs[] = { }; +static const struct mfd_cell adp5589_devs[] = { + MFD_CELL_NAME("adp5589-keys"), + MFD_CELL_NAME("adp5589-gpio"), + MFD_CELL_NAME("adp5589-pwm"), + +}; + static const struct regmap_range adp5585_volatile_ranges[] = { regmap_reg_range(ADP5585_ID, ADP5585_GPI_STATUS_B), }; @@ -34,6 +41,15 @@ static const struct regmap_access_table adp5585_volatile_regs = { .n_yes_ranges = ARRAY_SIZE(adp5585_volatile_ranges), }; +static const struct regmap_range adp5589_volatile_ranges[] = { + regmap_reg_range(ADP5585_ID, ADP5589_GPI_STATUS_C), +}; + +static const struct regmap_access_table adp5589_volatile_regs = { + .yes_ranges = adp5589_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(adp5589_volatile_ranges), +}; + /* * Chip variants differ in the default configuration of pull-up and pull-down * resistors, and therefore have different default register values: @@ -77,10 +93,52 @@ static const u8 adp5585_regmap_defaults_04[ADP5585_MAX_REG + 1] = { /* 0x38 */ 0x00, 0x00, 0x00, 0x00, 0x00, }; +static const u8 adp5589_regmap_defaults_00[ADP5589_MAX_REG + 1] = { + /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x38 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x48 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static const u8 adp5589_regmap_defaults_01[ADP5589_MAX_REG + 1] = { + /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x38 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + /* 0x40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x48 */ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, +}; + +static const u8 adp5589_regmap_defaults_02[ADP5589_MAX_REG + 1] = { + /* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x18 */ 0x00, 0x41, 0x01, 0x00, 0x11, 0x04, 0x00, 0x00, + /* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x38 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 0x48 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + enum adp5585_regmap_type { ADP5585_REGMAP_00, ADP5585_REGMAP_02, ADP5585_REGMAP_04, + ADP5589_REGMAP_00, + ADP5589_REGMAP_01, + ADP5589_REGMAP_02, }; static const struct regmap_config adp5585_regmap_configs[] = { @@ -111,6 +169,131 @@ static const struct regmap_config adp5585_regmap_configs[] = { .reg_defaults_raw = adp5585_regmap_defaults_04, .num_reg_defaults_raw = sizeof(adp5585_regmap_defaults_04), }, + [ADP5589_REGMAP_00] = { + .reg_bits = 8, + .val_bits = 8, + .max_register = ADP5589_MAX_REG, + .volatile_table = &adp5589_volatile_regs, + .cache_type = REGCACHE_MAPLE, + .reg_defaults_raw = adp5589_regmap_defaults_00, + .num_reg_defaults_raw = sizeof(adp5589_regmap_defaults_00), + }, + [ADP5589_REGMAP_01] = { + .reg_bits = 8, + .val_bits = 8, + .max_register = ADP5589_MAX_REG, + .volatile_table = &adp5589_volatile_regs, + .cache_type = REGCACHE_MAPLE, + .reg_defaults_raw = adp5589_regmap_defaults_01, + .num_reg_defaults_raw = sizeof(adp5589_regmap_defaults_01), + }, + [ADP5589_REGMAP_02] = { + .reg_bits = 8, + .val_bits = 8, + .max_register = ADP5589_MAX_REG, + .volatile_table = &adp5589_volatile_regs, + .cache_type = REGCACHE_MAPLE, + .reg_defaults_raw = adp5589_regmap_defaults_02, + .num_reg_defaults_raw = sizeof(adp5589_regmap_defaults_02), + }, +}; + +static const struct adp5585_regs adp5585_regs = { + .debounce_dis_a = ADP5585_DEBOUNCE_DIS_A, + .rpull_cfg_a = ADP5585_RPULL_CONFIG_A, + .gpo_data_a = ADP5585_GPO_DATA_OUT_A, + .gpo_out_a = ADP5585_GPO_OUT_MODE_A, + .gpio_dir_a = ADP5585_GPIO_DIRECTION_A, + .gpi_stat_a = ADP5585_GPI_STATUS_A, + .pwm_cfg = ADP5585_PWM_CFG, + .pwm_offt_low = ADP5585_PWM_OFFT_LOW, + .pwm_ont_low = ADP5585_PWM_ONT_LOW, + .gen_cfg = ADP5585_GENERAL_CFG, + .ext_cfg = ADP5585_PIN_CONFIG_C, +}; + +static const struct adp5585_regs adp5589_regs = { + .debounce_dis_a = ADP5589_DEBOUNCE_DIS_A, + .rpull_cfg_a = ADP5589_RPULL_CONFIG_A, + .gpo_data_a = ADP5589_GPO_DATA_OUT_A, + .gpo_out_a = ADP5589_GPO_OUT_MODE_A, + .gpio_dir_a = ADP5589_GPIO_DIRECTION_A, + .gpi_stat_a = ADP5589_GPI_STATUS_A, + .pwm_cfg = ADP5589_PWM_CFG, + .pwm_offt_low = ADP5589_PWM_OFFT_LOW, + .pwm_ont_low = ADP5589_PWM_ONT_LOW, + .gen_cfg = ADP5589_GENERAL_CFG, + .ext_cfg = ADP5589_PIN_CONFIG_D, +}; + +static const struct adp5585_info adp5585_info = { + .adp5585_devs = adp5585_devs, + .regmap_config = &adp5585_regmap_configs[ADP5585_REGMAP_00], + .n_devs = ARRAY_SIZE(adp5585_devs), + .id = ADP5585_MAN_ID_VALUE, + .regs = &adp5585_regs, + .max_rows = ADP5585_MAX_ROW_NUM, + .max_cols = ADP5585_MAX_COL_NUM, +}; + +static const struct adp5585_info adp5585_01_info = { + .adp5585_devs = adp5585_devs, + .regmap_config = &adp5585_regmap_configs[ADP5585_REGMAP_00], + .n_devs = ARRAY_SIZE(adp5585_devs), + .id = ADP5585_MAN_ID_VALUE, + .regs = &adp5585_regs, + .max_rows = ADP5585_MAX_ROW_NUM, + .max_cols = ADP5585_MAX_COL_NUM, +}; + +static const struct adp5585_info adp5585_02_info = { + .adp5585_devs = adp5585_devs, + .regmap_config = &adp5585_regmap_configs[ADP5585_REGMAP_02], + .n_devs = ARRAY_SIZE(adp5585_devs), + .id = ADP5585_MAN_ID_VALUE, + .regs = &adp5585_regs, + .max_rows = ADP5585_MAX_ROW_NUM, + .max_cols = ADP5585_MAX_COL_NUM, +}; + +static const struct adp5585_info adp5585_04_info = { + .adp5585_devs = adp5585_devs, + .regmap_config = &adp5585_regmap_configs[ADP5585_REGMAP_04], + .n_devs = ARRAY_SIZE(adp5585_devs), + .id = ADP5585_MAN_ID_VALUE, + .regs = &adp5585_regs, + .max_rows = ADP5585_MAX_ROW_NUM, + .max_cols = ADP5585_MAX_COL_NUM, +}; + +static const struct adp5585_info adp5589_info = { + .adp5585_devs = adp5589_devs, + .regmap_config = &adp5585_regmap_configs[ADP5589_REGMAP_00], + .n_devs = ARRAY_SIZE(adp5589_devs), + .id = ADP5589_MAN_ID_VALUE, + .regs = &adp5589_regs, + .max_rows = ADP5589_MAX_ROW_NUM, + .max_cols = ADP5589_MAX_COL_NUM, +}; + +static const struct adp5585_info adp5589_01_info = { + .adp5585_devs = adp5589_devs, + .regmap_config = &adp5585_regmap_configs[ADP5589_REGMAP_01], + .n_devs = ARRAY_SIZE(adp5589_devs), + .id = ADP5589_MAN_ID_VALUE, + .regs = &adp5589_regs, + .max_rows = ADP5589_MAX_ROW_NUM, + .max_cols = ADP5589_MAX_COL_NUM, +}; + +static const struct adp5585_info adp5589_02_info = { + .adp5585_devs = adp5589_devs, + .regmap_config = &adp5585_regmap_configs[ADP5589_REGMAP_02], + .n_devs = ARRAY_SIZE(adp5589_devs), + .id = ADP5589_MAN_ID_VALUE, + .regs = &adp5589_regs, + .max_rows = ADP5589_MAX_ROW_NUM, + .max_cols = ADP5589_MAX_COL_NUM, }; static void adp5585_osc_disable(void *data) @@ -122,7 +305,7 @@ static void adp5585_osc_disable(void *data) static int adp5585_i2c_probe(struct i2c_client *i2c) { - const struct regmap_config *regmap_config; + const struct adp5585_info *info; struct adp5585_dev *adp5585; unsigned int id; int ret; @@ -133,8 +316,13 @@ static int adp5585_i2c_probe(struct i2c_client *i2c) i2c_set_clientdata(i2c, adp5585); - regmap_config = i2c_get_match_data(i2c); - adp5585->regmap = devm_regmap_init_i2c(i2c, regmap_config); + info = i2c_get_match_data(i2c); + if (!info) + return -ENODEV; + + adp5585->info = info; + + adp5585->regmap = devm_regmap_init_i2c(i2c, info->regmap_config); if (IS_ERR(adp5585->regmap)) return dev_err_probe(&i2c->dev, PTR_ERR(adp5585->regmap), "Failed to initialize register map\n"); @@ -144,7 +332,8 @@ static int adp5585_i2c_probe(struct i2c_client *i2c) return dev_err_probe(&i2c->dev, ret, "Failed to read device ID\n"); - if ((id & ADP5585_MAN_ID_MASK) != ADP5585_MAN_ID_VALUE) + id &= ADP5585_MAN_ID_MASK; + if (id != adp5585->info->id) return dev_err_probe(&i2c->dev, -ENODEV, "Invalid device ID 0x%02x\n", id); @@ -158,8 +347,8 @@ static int adp5585_i2c_probe(struct i2c_client *i2c) return ret; ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO, - adp5585_devs, ARRAY_SIZE(adp5585_devs), - NULL, 0, NULL); + adp5585->info->adp5585_devs, + adp5585->info->n_devs, NULL, 0, NULL); if (ret) return dev_err_probe(&i2c->dev, ret, "Failed to add child devices\n"); @@ -191,19 +380,31 @@ static DEFINE_SIMPLE_DEV_PM_OPS(adp5585_pm, adp5585_suspend, adp5585_resume); static const struct of_device_id adp5585_of_match[] = { { .compatible = "adi,adp5585-00", - .data = &adp5585_regmap_configs[ADP5585_REGMAP_00], + .data = &adp5585_info, }, { .compatible = "adi,adp5585-01", - .data = &adp5585_regmap_configs[ADP5585_REGMAP_00], + .data = &adp5585_01_info, }, { .compatible = "adi,adp5585-02", - .data = &adp5585_regmap_configs[ADP5585_REGMAP_02], + .data = &adp5585_02_info, }, { .compatible = "adi,adp5585-03", - .data = &adp5585_regmap_configs[ADP5585_REGMAP_00], + .data = &adp5585_info, }, { .compatible = "adi,adp5585-04", - .data = &adp5585_regmap_configs[ADP5585_REGMAP_04], + .data = &adp5585_04_info, + }, { + .compatible = "adi,adp5589-00", + .data = &adp5589_info, + }, { + .compatible = "adi,adp5589-01", + .data = &adp5589_01_info, + }, { + .compatible = "adi,adp5589-02", + .data = &adp5589_02_info, + }, { + .compatible = "adi,adp5589", + .data = &adp5589_info, }, { /* sentinel */ } }; diff --git a/include/linux/mfd/adp5585.h b/include/linux/mfd/adp5585.h index 016033cd68e46757aca86d21dd37025fd354b801..dffe1449de01dacf8fe78cf0e87d1f176d11f620 100644 --- a/include/linux/mfd/adp5585.h +++ b/include/linux/mfd/adp5585.h @@ -104,9 +104,11 @@ #define ADP5585_INT_CFG BIT(1) #define ADP5585_RST_CFG BIT(0) #define ADP5585_INT_EN 0x3c - #define ADP5585_MAX_REG ADP5585_INT_EN +#define ADP5585_MAX_ROW_NUM 6 +#define ADP5585_MAX_COL_NUM 5 + /* * Bank 0 covers pins "GPIO 1/R0" to "GPIO 6/R5", numbered 0 to 5 by the * driver, and bank 1 covers pins "GPIO 7/C0" to "GPIO 11/C4", numbered 6 to @@ -117,10 +119,63 @@ #define ADP5585_BANK(n) ((n) >= 6 ? 1 : 0) #define ADP5585_BIT(n) ((n) >= 6 ? BIT((n) - 6) : BIT(n)) +/* ADP5589 */ +#define ADP5589_MAN_ID_VALUE 0x10 +#define ADP5589_GPI_STATUS_A 0x16 +#define ADP5589_GPI_STATUS_C 0x18 +#define ADP5589_RPULL_CONFIG_A 0x19 +#define ADP5589_DEBOUNCE_DIS_A 0x27 +#define ADP5589_GPO_DATA_OUT_A 0x2a +#define ADP5589_GPO_OUT_MODE_A 0x2d +#define ADP5589_GPIO_DIRECTION_A 0x30 +#define ADP5589_PWM_OFFT_LOW 0x3e +#define ADP5589_PWM_ONT_LOW 0x40 +#define ADP5589_PWM_CFG 0x42 +#define ADP5589_PIN_CONFIG_D 0x4C +#define ADP5589_GENERAL_CFG 0x4d +#define ADP5589_INT_EN 0x4e +#define ADP5589_MAX_REG ADP5589_INT_EN + +#define ADP5589_MAX_ROW_NUM 8 +#define ADP5589_MAX_COL_NUM 11 + +/* + * Bank 0 covers pins "GPIO 1/R0" to "GPIO 8/R7", numbered 0 to 7 by the + * driver, bank 1 covers pins "GPIO 9/C0" to "GPIO 16/C7", numbered 8 to + * 15 and bank 3 covers pins "GPIO 17/C8" to "GPIO 19/C10", numbered 16 to 18. + */ +#define ADP5589_BANK(n) ((n) >> 3) +#define ADP5589_BIT(n) BIT((n) & 0x7) + +struct adp5585_regs { + unsigned int debounce_dis_a; + unsigned int rpull_cfg_a; + unsigned int gpo_data_a; + unsigned int gpo_out_a; + unsigned int gpio_dir_a; + unsigned int gpi_stat_a; + unsigned int pwm_cfg; + unsigned int pwm_offt_low; + unsigned int pwm_ont_low; + unsigned int gen_cfg; + unsigned int ext_cfg; +}; + +struct adp5585_info { + const struct mfd_cell *adp5585_devs; + const struct regmap_config *regmap_config; + const struct adp5585_regs *regs; + unsigned int n_devs; + unsigned int id; + u8 max_rows; + u8 max_cols; +}; + struct regmap; struct adp5585_dev { struct regmap *regmap; + const struct adp5585_info *info; }; #endif From patchwork Tue Apr 15 14:49:23 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= X-Patchwork-Id: 881488 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 40C3C29B76B; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728560; cv=none; b=sbPys9MM5IDQT4Q6pH93eGGv/Deo19zIADkD5Oz2Xs9/2UoQ6IvFVeADPhcNtzardJZWmdWRKXc2GLvdKF/o4IiHjLpOojLIYRFNn8swZgBxihG3tKuIMYs+DeG9VTZqKjWS0Fb58j6P1Y1M4nZNgZZPXnyvIMqsYKm+GZfMTag= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728560; c=relaxed/simple; bh=rLn0yCnCMtxYmTQlgKBvmj60HZfLQgZ4sobAUNp/SKs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VHjpA5hECZ6Qf+Bm9keZkl7pla0lqwYH9T+YGyOT8bUWNE4qf6Lma4Arm79aH9syFi/DPd5ObXY8x92mSk9J6UARyzm/dLWJUF/e9yitPWiCxOSCD84rGA6Oa8l1oTTeQFfAYEjZjazniffPMEyCmgSJl3C7h9qDsEjLSFo4K8s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=knTRAHNe; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="knTRAHNe" Received: by smtp.kernel.org (Postfix) with ESMTPS id 8FBA8C4CEF9; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744728559; bh=rLn0yCnCMtxYmTQlgKBvmj60HZfLQgZ4sobAUNp/SKs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=knTRAHNeBESEs4jntpiRg7xgQni1uw0KA4pUcUIv5LD0Hau6xNh5pvM1Vozg6/kRN Eg7+2kN2q4Mex9kjaxgayvVhsRZtICaFhniZ17cV42dT8e0bClPJk2KjtIYJ8/uPGg xmxxpI49RBCS4r9yVpELrsn3DfEygr/93W9S9A1YpgvyVwjqMLF6bC8Y+V7Apcle+C fARdTxJcOqOocHoIp+YKonhO5SFMBSeghOlU+Z7er1PRw4VZ3JquogjN0LhPLE81Ra u9e48Xc+3xJ1EFGAdjpcQ5LMSEJtdWZEjdnuBr+ESFYQ3qT1JBwG/RB45sNoFPfK7n sqXdfylyiZK/w== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 86578C369BD; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Tue, 15 Apr 2025 15:49:23 +0100 Subject: [PATCH v2 07/17] gpio: adp5585: add support for the ad5589 expander Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250415-dev-adp5589-fw-v2-7-3a799c3ed812@analog.com> References: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> In-Reply-To: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> To: linux-gpio@vger.kernel.org, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-input@vger.kernel.org Cc: Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Linus Walleij , Bartosz Golaszewski , Dmitry Torokhov , Laurent Pinchart , Liu Ying X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1744728560; l=9249; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=dhOobqAdoEg5vowYXwvlopJTrVq+rE29macO+WfMrlo=; b=NPdwKzFXvw/wJ77ViAHccMl95xnzYbI9UR22fP4x8t3W8gwAn/YYLtjK2i5angpN366ChzJli XHVYYhung9XAEeyXRhqTtb7qGHAb5GGzE2ObAQp3tgvpagZz0moBRsV X-Developer-Key: i=nuno.sa@analog.com; a=ed25519; pk=3NQwYA013OUYZsmDFBf8rmyyr5iQlxV/9H4/Df83o1E= X-Endpoint-Received: by B4 Relay for nuno.sa@analog.com/20231116 with auth_id=100 X-Original-From: =?utf-8?q?Nuno_S=C3=A1?= Reply-To: nuno.sa@analog.com From: Nuno Sá Support the adp5589 I/O expander which supports up to 19 pins. We need to add a chip_info based struct since accessing register "banks" and "bits" differs between devices. Also some register addresses are different. Acked-by: Linus Walleij Signed-off-by: Nuno Sá --- drivers/gpio/gpio-adp5585.c | 121 ++++++++++++++++++++++++++++++++------------ 1 file changed, 88 insertions(+), 33 deletions(-) diff --git a/drivers/gpio/gpio-adp5585.c b/drivers/gpio/gpio-adp5585.c index d5c0f1b267c82a5002b50cbb7a108166439e4785..d8f8d5513d7f6a9acf5bdecccacc89c4615ce237 100644 --- a/drivers/gpio/gpio-adp5585.c +++ b/drivers/gpio/gpio-adp5585.c @@ -4,6 +4,7 @@ * * Copyright 2022 NXP * Copyright 2024 Ideas on Board Oy + * Copyright 2025 Analog Devices, Inc. */ #include @@ -14,21 +15,49 @@ #include #include -#define ADP5585_GPIO_MAX 11 +struct adp5585_gpio_chip { + unsigned int max_gpio; + int (*bank)(unsigned int off); + int (*bit)(unsigned int off); + bool has_bias_hole; +}; struct adp5585_gpio_dev { struct gpio_chip gpio_chip; + const struct adp5585_gpio_chip *info; struct regmap *regmap; + const struct adp5585_regs *regs; }; +static int adp5585_gpio_bank(unsigned int off) +{ + return ADP5585_BANK(off); +} + +static int adp5585_gpio_bit(unsigned int off) +{ + return ADP5585_BIT(off); +} + +static int adp5589_gpio_bank(unsigned int off) +{ + return ADP5589_BANK(off); +} + +static int adp5589_gpio_bit(unsigned int off) +{ + return ADP5589_BIT(off); +} + static int adp5585_gpio_get_direction(struct gpio_chip *chip, unsigned int off) { struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip); - unsigned int bank = ADP5585_BANK(off); - unsigned int bit = ADP5585_BIT(off); + const struct adp5585_regs *regs = adp5585_gpio->regs; + unsigned int bank = adp5585_gpio->info->bank(off); + unsigned int bit = adp5585_gpio->info->bit(off); unsigned int val; - regmap_read(adp5585_gpio->regmap, ADP5585_GPIO_DIRECTION_A + bank, &val); + regmap_read(adp5585_gpio->regmap, regs->gpio_dir_a + bank, &val); return val & bit ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN; } @@ -36,35 +65,37 @@ static int adp5585_gpio_get_direction(struct gpio_chip *chip, unsigned int off) static int adp5585_gpio_direction_input(struct gpio_chip *chip, unsigned int off) { struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip); - unsigned int bank = ADP5585_BANK(off); - unsigned int bit = ADP5585_BIT(off); + const struct adp5585_regs *regs = adp5585_gpio->regs; + unsigned int bank = adp5585_gpio->info->bank(off); + unsigned int bit = adp5585_gpio->info->bit(off); - return regmap_clear_bits(adp5585_gpio->regmap, - ADP5585_GPIO_DIRECTION_A + bank, bit); + return regmap_clear_bits(adp5585_gpio->regmap, regs->gpio_dir_a + bank, + bit); } static int adp5585_gpio_direction_output(struct gpio_chip *chip, unsigned int off, int val) { struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip); - unsigned int bank = ADP5585_BANK(off); - unsigned int bit = ADP5585_BIT(off); + const struct adp5585_regs *regs = adp5585_gpio->regs; + unsigned int bank = adp5585_gpio->info->bank(off); + unsigned int bit = adp5585_gpio->info->bit(off); int ret; - ret = regmap_update_bits(adp5585_gpio->regmap, - ADP5585_GPO_DATA_OUT_A + bank, bit, - val ? bit : 0); + ret = regmap_update_bits(adp5585_gpio->regmap, regs->gpo_data_a + bank, + bit, val ? bit : 0); if (ret) return ret; - return regmap_set_bits(adp5585_gpio->regmap, - ADP5585_GPIO_DIRECTION_A + bank, bit); + return regmap_set_bits(adp5585_gpio->regmap, regs->gpio_dir_a + bank, + bit); } static int adp5585_gpio_get_value(struct gpio_chip *chip, unsigned int off) { struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip); - unsigned int bank = ADP5585_BANK(off); - unsigned int bit = ADP5585_BIT(off); + const struct adp5585_regs *regs = adp5585_gpio->regs; + unsigned int bank = adp5585_gpio->info->bank(off); + unsigned int bit = adp5585_gpio->info->bit(off); unsigned int reg; unsigned int val; @@ -79,8 +110,8 @@ static int adp5585_gpio_get_value(struct gpio_chip *chip, unsigned int off) * .direction_input(), .direction_output() or .set() operations racing * with this. */ - regmap_read(adp5585_gpio->regmap, ADP5585_GPIO_DIRECTION_A + bank, &val); - reg = val & bit ? ADP5585_GPO_DATA_OUT_A : ADP5585_GPI_STATUS_A; + regmap_read(adp5585_gpio->regmap, regs->gpio_dir_a + bank, &val); + reg = val & bit ? regs->gpo_data_a : regs->gpi_stat_a; regmap_read(adp5585_gpio->regmap, reg + bank, &val); return !!(val & bit); @@ -90,17 +121,19 @@ static int adp5585_gpio_set_value(struct gpio_chip *chip, unsigned int off, int val) { struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip); - unsigned int bank = ADP5585_BANK(off); - unsigned int bit = ADP5585_BIT(off); + const struct adp5585_regs *regs = adp5585_gpio->regs; + unsigned int bank = adp5585_gpio->info->bank(off); + unsigned int bit = adp5585_gpio->info->bit(off); - return regmap_update_bits(adp5585_gpio->regmap, - ADP5585_GPO_DATA_OUT_A + bank, + return regmap_update_bits(adp5585_gpio->regmap, regs->gpo_data_a + bank, bit, val ? bit : 0); } static int adp5585_gpio_set_bias(struct adp5585_gpio_dev *adp5585_gpio, unsigned int off, unsigned int bias) { + const struct adp5585_gpio_chip *info = adp5585_gpio->info; + const struct adp5585_regs *regs = adp5585_gpio->regs; unsigned int bit, reg, mask, val; /* @@ -108,8 +141,10 @@ static int adp5585_gpio_set_bias(struct adp5585_gpio_dev *adp5585_gpio, * consecutive registers ADP5585_RPULL_CONFIG_*, with a hole of 4 bits * after R5. */ - bit = off * 2 + (off > 5 ? 4 : 0); - reg = ADP5585_RPULL_CONFIG_A + bit / 8; + bit = off * 2; + if (info->has_bias_hole) + bit += (off > 5 ? 4 : 0); + reg = regs->rpull_cfg_a + bit / 8; mask = ADP5585_Rx_PULL_CFG_MASK << (bit % 8); val = bias << (bit % 8); @@ -119,22 +154,24 @@ static int adp5585_gpio_set_bias(struct adp5585_gpio_dev *adp5585_gpio, static int adp5585_gpio_set_drive(struct adp5585_gpio_dev *adp5585_gpio, unsigned int off, enum pin_config_param drive) { - unsigned int bank = ADP5585_BANK(off); - unsigned int bit = ADP5585_BIT(off); + const struct adp5585_regs *regs = adp5585_gpio->regs; + unsigned int bank = adp5585_gpio->info->bank(off); + unsigned int bit = adp5585_gpio->info->bit(off); return regmap_update_bits(adp5585_gpio->regmap, - ADP5585_GPO_OUT_MODE_A + bank, bit, + regs->gpo_out_a + bank, bit, drive == PIN_CONFIG_DRIVE_OPEN_DRAIN ? bit : 0); } static int adp5585_gpio_set_debounce(struct adp5585_gpio_dev *adp5585_gpio, unsigned int off, unsigned int debounce) { - unsigned int bank = ADP5585_BANK(off); - unsigned int bit = ADP5585_BIT(off); + const struct adp5585_regs *regs = adp5585_gpio->regs; + unsigned int bank = adp5585_gpio->info->bank(off); + unsigned int bit = adp5585_gpio->info->bit(off); return regmap_update_bits(adp5585_gpio->regmap, - ADP5585_DEBOUNCE_DIS_A + bank, bit, + regs->debounce_dis_a + bank, bit, debounce ? 0 : bit); } @@ -175,6 +212,7 @@ static int adp5585_gpio_set_config(struct gpio_chip *chip, unsigned int off, static int adp5585_gpio_probe(struct platform_device *pdev) { struct adp5585_dev *adp5585 = dev_get_drvdata(pdev->dev.parent); + const struct platform_device_id *id = platform_get_device_id(pdev); struct adp5585_gpio_dev *adp5585_gpio; struct device *dev = &pdev->dev; struct gpio_chip *gc; @@ -185,6 +223,11 @@ static int adp5585_gpio_probe(struct platform_device *pdev) return -ENOMEM; adp5585_gpio->regmap = adp5585->regmap; + adp5585_gpio->regs = adp5585->info->regs; + + adp5585_gpio->info = (const struct adp5585_gpio_chip *)id->driver_data; + if (!adp5585_gpio->info) + return -ENODEV; device_set_of_node_from_dev(dev, dev->parent); @@ -199,7 +242,7 @@ static int adp5585_gpio_probe(struct platform_device *pdev) gc->can_sleep = true; gc->base = -1; - gc->ngpio = ADP5585_GPIO_MAX; + gc->ngpio = adp5585->info->max_cols + adp5585->info->max_rows; gc->label = pdev->name; gc->owner = THIS_MODULE; @@ -211,8 +254,20 @@ static int adp5585_gpio_probe(struct platform_device *pdev) return 0; } +static const struct adp5585_gpio_chip adp5585_gpio_chip_info = { + .bank = adp5585_gpio_bank, + .bit = adp5585_gpio_bit, + .has_bias_hole = true, +}; + +static const struct adp5585_gpio_chip adp5589_gpio_chip_info = { + .bank = adp5589_gpio_bank, + .bit = adp5589_gpio_bit, +}; + static const struct platform_device_id adp5585_gpio_id_table[] = { - { "adp5585-gpio" }, + { "adp5585-gpio", (kernel_ulong_t)&adp5585_gpio_chip_info }, + { "adp5589-gpio", (kernel_ulong_t)&adp5589_gpio_chip_info }, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(platform, adp5585_gpio_id_table); From patchwork Tue Apr 15 14:49:26 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= X-Patchwork-Id: 881486 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7AB3529B795; Tue, 15 Apr 2025 14:49:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728560; cv=none; b=T6N1STyAg3nWIQ2VhOCvQDfDmx8oUuKjF2fcq5y1Y4dAWsd9jdHmtNGRPBbbp1Pz8rench5lMEwsP4xfS3NRirghhQnflAuH74fZBTSPVPpAZLivDlNH1HPxff/sEqTDaNzBoVLFM5ey6Zhhye+SrR+nrMSOxHf51H09mqJnWXU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728560; c=relaxed/simple; bh=i3C2dA7Zm42ozfifpBhxMdmdavdlGys0xAjJ3Sqzv6Y=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KD5a5hdTS6zn+I9l41/qrFZQqIfKyZDFpsL/H50M3fOFqR+qUraaoSQ031XFaQiUZK3YxgrzAB0BqPbxQsKSHb8HOyqcQndFVhAoHgq6NY1uGISXcU0axXPyesAcIdI2DzbaaK4aVmeuRzIShDE0ZhZzGTSNxD0OzhzOxw5vj5g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=H2Fqcrgk; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="H2Fqcrgk" Received: by smtp.kernel.org (Postfix) with ESMTPS id B9B85C4CEF0; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744728559; bh=i3C2dA7Zm42ozfifpBhxMdmdavdlGys0xAjJ3Sqzv6Y=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=H2FqcrgktNmGmRUhQPNm3eQ+OZESgJ7sCOQVhRKrEhYngMcRcGLobbwz5J99W0q2f JTCKGgN1RhnrA+ZBLSh4ESwS2cKAjcZZNhRQJbIS5v0Dy+zy+aU2YdP1pLb60QSC0u oCndJ5yyDc+F3cqmTXXHUjMlrjwuA2pcyiaXewXr1dc9Ux/wiNfYJ2QagdM6Ej1mGQ uld4GVoxAZeBdBZ3+h1K99js9cN5caVmntrhBGsSJmAiPTlPR2ZAoOCqiJPfXfX1OU 0/Ve0pT11z/vmwGCQZxtygRTRv3wHWEipSQjNxfqi34uowoox4oxwB7OEHjueFgBZQ 9Ff2ZjDwbruKQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id B198CC369BD; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Tue, 15 Apr 2025 15:49:26 +0100 Subject: [PATCH v2 10/17] mfd: adp5585: add support for key events Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250415-dev-adp5589-fw-v2-10-3a799c3ed812@analog.com> References: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> In-Reply-To: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> To: linux-gpio@vger.kernel.org, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-input@vger.kernel.org Cc: Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Linus Walleij , Bartosz Golaszewski , Dmitry Torokhov , Laurent Pinchart , Liu Ying X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1744728560; l=27276; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=oOvt8dNeycTcZnS5Bmf27/ApMZ7PleeDyVRB5OpU5ZU=; b=k87G0RymeiAyTS8NdtSo9ITviy+ex3lXpCzrDKUCzFF75jzTN6dHdXJpKDB7ueJ5alqvf0EC5 DZNBMdBdyGNCkkzdIlh0HEgI2GnLCAzXdy72cBa/Kv+zFqEwf9tas+e X-Developer-Key: i=nuno.sa@analog.com; a=ed25519; pk=3NQwYA013OUYZsmDFBf8rmyyr5iQlxV/9H4/Df83o1E= X-Endpoint-Received: by B4 Relay for nuno.sa@analog.com/20231116 with auth_id=100 X-Original-From: =?utf-8?q?Nuno_S=C3=A1?= Reply-To: nuno.sa@analog.com From: Nuno Sá This adds support for key events. Basically, it adds support for all the FW parsing and configuration of the keys (also making sure there's no overlaps). They can either be part of a matrix keymap (in which case events will be handled by an input device) or they can be gpi's (in which case events will be handled by the gpiochip device via gpio_keys). There's also support for unlock keys as for reset keys. This patch adds all the foundation needed by subsequent changes where the child devices (actually handling the events) can "register" a callback to handle the event. Also to note that enabling the internal oscillator in now done as part of adp5585_setup(). We also enable/disable the IRQ (if present) in the corresponding PM event. Signed-off-by: Nuno Sá --- drivers/mfd/adp5585.c | 551 +++++++++++++++++++++++++++++++++++++++++++- include/linux/mfd/adp5585.h | 96 ++++++++ 2 files changed, 642 insertions(+), 5 deletions(-) diff --git a/drivers/mfd/adp5585.c b/drivers/mfd/adp5585.c index c3586c0d6aa2e7e7d94667993410610be7fc3672..c1d51d50dca6c9367d4a1b98a4f8bbec12dbf90b 100644 --- a/drivers/mfd/adp5585.c +++ b/drivers/mfd/adp5585.c @@ -8,11 +8,13 @@ */ #include +#include #include #include #include #include #include +#include #include #include #include @@ -205,11 +207,19 @@ static const struct adp5585_regs adp5585_regs = { .gpo_out_a = ADP5585_GPO_OUT_MODE_A, .gpio_dir_a = ADP5585_GPIO_DIRECTION_A, .gpi_stat_a = ADP5585_GPI_STATUS_A, + .gpi_ev_a = ADP5585_GPI_EVENT_EN_A, + .gpi_int_lvl_a = ADP5585_GPI_INT_LEVEL_A, .pwm_cfg = ADP5585_PWM_CFG, .pwm_offt_low = ADP5585_PWM_OFFT_LOW, .pwm_ont_low = ADP5585_PWM_ONT_LOW, + .reset_cfg = ADP5585_RESET_CFG, .gen_cfg = ADP5585_GENERAL_CFG, .ext_cfg = ADP5585_PIN_CONFIG_C, + .pin_cfg_a = ADP5585_PIN_CONFIG_A, + .poll_ptime_cfg = ADP5585_POLL_PTIME_CFG, + .int_en = ADP5585_INT_EN, + .reset1_event_a = ADP5585_RESET1_EVENT_A, + .reset2_event_a = ADP5585_RESET2_EVENT_A, }; static const struct adp5585_regs adp5589_regs = { @@ -219,11 +229,19 @@ static const struct adp5585_regs adp5589_regs = { .gpo_out_a = ADP5589_GPO_OUT_MODE_A, .gpio_dir_a = ADP5589_GPIO_DIRECTION_A, .gpi_stat_a = ADP5589_GPI_STATUS_A, + .gpi_ev_a = ADP5589_GPI_EVENT_EN_A, + .gpi_int_lvl_a = ADP5589_GPI_INT_LEVEL_A, .pwm_cfg = ADP5589_PWM_CFG, .pwm_offt_low = ADP5589_PWM_OFFT_LOW, .pwm_ont_low = ADP5589_PWM_ONT_LOW, + .reset_cfg = ADP5589_RESET_CFG, .gen_cfg = ADP5589_GENERAL_CFG, .ext_cfg = ADP5589_PIN_CONFIG_D, + .pin_cfg_a = ADP5589_PIN_CONFIG_A, + .poll_ptime_cfg = ADP5589_POLL_PTIME_CFG, + .int_en = ADP5589_INT_EN, + .reset1_event_a = ADP5589_RESET1_EVENT_A, + .reset2_event_a = ADP5589_RESET2_EVENT_A, }; static const struct adp5585_info adp5585_info = { @@ -234,6 +252,8 @@ static const struct adp5585_info adp5585_info = { .regs = &adp5585_regs, .max_rows = ADP5585_MAX_ROW_NUM, .max_cols = ADP5585_MAX_COL_NUM, + .gpi_ev_base = ADP5585_GPI_EVENT_START, + .gpi_ev_end = ADP5585_GPI_EVENT_END, }; static const struct adp5585_info adp5585_01_info = { @@ -241,9 +261,12 @@ static const struct adp5585_info adp5585_01_info = { .regmap_config = &adp5585_regmap_configs[ADP5585_REGMAP_00], .n_devs = ARRAY_SIZE(adp5585_devs), .id = ADP5585_MAN_ID_VALUE, + .has_row5 = true, .regs = &adp5585_regs, .max_rows = ADP5585_MAX_ROW_NUM, .max_cols = ADP5585_MAX_COL_NUM, + .gpi_ev_base = ADP5585_GPI_EVENT_START, + .gpi_ev_end = ADP5585_GPI_EVENT_END, }; static const struct adp5585_info adp5585_02_info = { @@ -254,6 +277,8 @@ static const struct adp5585_info adp5585_02_info = { .regs = &adp5585_regs, .max_rows = ADP5585_MAX_ROW_NUM, .max_cols = ADP5585_MAX_COL_NUM, + .gpi_ev_base = ADP5585_GPI_EVENT_START, + .gpi_ev_end = ADP5585_GPI_EVENT_END, }; static const struct adp5585_info adp5585_04_info = { @@ -264,6 +289,8 @@ static const struct adp5585_info adp5585_04_info = { .regs = &adp5585_regs, .max_rows = ADP5585_MAX_ROW_NUM, .max_cols = ADP5585_MAX_COL_NUM, + .gpi_ev_base = ADP5585_GPI_EVENT_START, + .gpi_ev_end = ADP5585_GPI_EVENT_END, }; static const struct adp5585_info adp5589_info = { @@ -271,9 +298,13 @@ static const struct adp5585_info adp5589_info = { .regmap_config = &adp5585_regmap_configs[ADP5589_REGMAP_00], .n_devs = ARRAY_SIZE(adp5589_devs), .id = ADP5589_MAN_ID_VALUE, + .has_row5 = true, + .has_unlock = true, .regs = &adp5589_regs, .max_rows = ADP5589_MAX_ROW_NUM, .max_cols = ADP5589_MAX_COL_NUM, + .gpi_ev_base = ADP5589_GPI_EVENT_START, + .gpi_ev_end = ADP5589_GPI_EVENT_END, }; static const struct adp5585_info adp5589_01_info = { @@ -281,9 +312,13 @@ static const struct adp5585_info adp5589_01_info = { .regmap_config = &adp5585_regmap_configs[ADP5589_REGMAP_01], .n_devs = ARRAY_SIZE(adp5589_devs), .id = ADP5589_MAN_ID_VALUE, + .has_row5 = true, + .has_unlock = true, .regs = &adp5589_regs, .max_rows = ADP5589_MAX_ROW_NUM, .max_cols = ADP5589_MAX_COL_NUM, + .gpi_ev_base = ADP5589_GPI_EVENT_START, + .gpi_ev_end = ADP5589_GPI_EVENT_END, }; static const struct adp5585_info adp5589_02_info = { @@ -291,11 +326,379 @@ static const struct adp5585_info adp5589_02_info = { .regmap_config = &adp5585_regmap_configs[ADP5589_REGMAP_02], .n_devs = ARRAY_SIZE(adp5589_devs), .id = ADP5589_MAN_ID_VALUE, + .has_row5 = true, + .has_unlock = true, .regs = &adp5589_regs, .max_rows = ADP5589_MAX_ROW_NUM, .max_cols = ADP5589_MAX_COL_NUM, + .gpi_ev_base = ADP5589_GPI_EVENT_START, + .gpi_ev_end = ADP5589_GPI_EVENT_END, }; +static int adp5585_keys_validate_key(const struct adp5585_dev *adp5585, u32 key, + bool is_gpi) +{ + const struct adp5585_info *info = adp5585->info; + struct device *dev = adp5585->dev; + u32 row, col; + + if (is_gpi) { + u32 gpi = key - adp5585->info->gpi_ev_base; + + if (!info->has_row5 && gpi == ADP5585_ROW5) + return dev_err_probe(dev, -EINVAL, + "Invalid unlock/reset GPI(%u) not supported\n", + gpi); + + /* check if it's being used in the keypad */ + if (test_bit(gpi, adp5585->keypad)) + return dev_err_probe(dev, -EINVAL, + "Invalid unlock/reset GPI(%u) being used in the keypad\n", + gpi); + + return 0; + } + + row = (key - 1) / info->max_cols; + col = (key - 1) % info->max_cols; + + /* both the row and col must be part of the keypad */ + if (test_bit(row, adp5585->keypad) && + test_bit(col + info->max_rows, adp5585->keypad)) + return 0; + + return dev_err_probe(dev, -EINVAL, + "Invalid unlock/reset key(%u) not used in the keypad\n", key); +} + +static int adp5585_keys_parse_array(const struct adp5585_dev *adp5585, + const char *prop, u32 *keys, u32 *n_keys, + u32 max_keys, bool reset_key) +{ + const struct adp5585_info *info = adp5585->info; + struct device *dev = adp5585->dev; + unsigned int key, max_keypad; + int ret; + + ret = device_property_count_u32(dev, prop); + if (ret < 0) + return 0; + + *n_keys = ret; + + if (!info->has_unlock && !reset_key) + return dev_err_probe(dev, -EOPNOTSUPP, + "Unlock keys not supported\n"); + + if (*n_keys > max_keys) + return dev_err_probe(dev, -EINVAL, + "Invalid number of keys(%u > %u) for %s\n", + *n_keys, max_keys, prop); + + ret = device_property_read_u32_array(dev, prop, keys, *n_keys); + if (ret) + return ret; + + max_keypad = adp5585->info->max_rows * adp5585->info->max_cols; + + for (key = 0; key < *n_keys; key++) { + /* part of the keypad... */ + if (in_range(keys[key], 1, max_keypad)) { + /* is it part of the keypad?! */ + ret = adp5585_keys_validate_key(adp5585, keys[key], + false); + if (ret) + return ret; + + continue; + } + + /* part of gpio-keys... */ + if (in_range(keys[key], adp5585->info->gpi_ev_base, + info->max_cols + info->max_rows)) { + /* is the GPI being used as part of the keypad?! */ + ret = adp5585_keys_validate_key(adp5585, keys[key], + true); + if (ret) + return ret; + + continue; + } + + if (!reset_key && keys[key] == 127) + continue; + + return dev_err_probe(dev, -EINVAL, "Invalid key(%u) for %s\n", + keys[key], prop); + } + + return 0; +} + +static int adp5585_keys_unlock_parse(struct adp5585_dev *adp5585) +{ + struct device *dev = adp5585->dev; + int ret; + + ret = adp5585_keys_parse_array(adp5585, "adi,unlock-keys", + adp5585->unlock_keys, + &adp5585->nkeys_unlock, + ARRAY_SIZE(adp5585->unlock_keys), false); + if (ret) + return ret; + if (!adp5585->nkeys_unlock) + /* no unlock keys */ + return 0; + + ret = device_property_read_u32(dev, "adi,unlock-trigger-sec", + &adp5585->unlock_time); + if (!ret) { + if (adp5585->unlock_time > ADP5585_MAX_UNLOCK_TIME_SEC) + return dev_err_probe(dev, -EINVAL, + "Invalid unlock time(%u > %d)\n", + adp5585->unlock_time, + ADP5585_MAX_UNLOCK_TIME_SEC); + } + + return 0; +} + +static int adp5585_keys_reset_parse(struct adp5585_dev *adp5585) +{ + const struct adp5585_info *info = adp5585->info; + struct device *dev = adp5585->dev; + u32 prop_val; + int ret; + + ret = adp5585_keys_parse_array(adp5585, "adi,reset1-keys", + adp5585->reset1_keys, + &adp5585->nkeys_reset1, + ARRAY_SIZE(adp5585->reset1_keys), true); + if (ret) + return ret; + + if (adp5585->nkeys_reset1 > 0) { + if (test_bit(ADP5585_ROW4, adp5585->keypad)) + return dev_err_probe(dev, -EINVAL, + "Invalid reset1 output(R4) being used in the keypad\n"); + + if (device_property_read_bool(dev, "adi,reset1-active-high")) + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET1_POL, 1); + } + + ret = adp5585_keys_parse_array(adp5585, "adi,reset2-keys", + adp5585->reset2_keys, + &adp5585->nkeys_reset2, + ARRAY_SIZE(adp5585->reset2_keys), true); + if (ret) + return ret; + + if (adp5585->nkeys_reset2 > 0) { + if (test_bit(info->max_rows + ADP5585_COL4, adp5585->keypad)) + return dev_err_probe(dev, -EINVAL, + "Invalid reset2 output(C4) being used in the keypad\n"); + + if (device_property_read_bool(dev, "adi,reset2-active-high")) + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET2_POL, 1); + } + + if (!adp5585->nkeys_reset1 && !adp5585->nkeys_reset2) + return 0; + + if (device_property_read_bool(dev, "adi,rst-passtrough-enable")) + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RST_PASSTHRU_EN, 1); + + ret = device_property_read_u32(dev, "adi,reset-trigger-ms", &prop_val); + if (!ret) { + switch (prop_val) { + case 0: + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 0); + break; + case 1000: + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 1); + break; + case 1500: + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 2); + break; + case 2000: + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 3); + break; + case 2500: + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 4); + break; + case 3000: + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 5); + break; + case 3500: + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 6); + break; + case 4000: + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 7); + break; + default: + return dev_err_probe(dev, -EINVAL, + "Invalid value(%u) for adi,reset-trigger-ms\n", + prop_val); + } + } + + ret = device_property_read_u32(dev, "adi,reset-pulse-width-us", + &prop_val); + if (!ret) { + switch (prop_val) { + case 500: + adp5585->reset_cfg |= FIELD_PREP(ADP5585_PULSE_WIDTH, 0); + break; + case 1000: + adp5585->reset_cfg |= FIELD_PREP(ADP5585_PULSE_WIDTH, 1); + break; + case 2000: + adp5585->reset_cfg |= FIELD_PREP(ADP5585_PULSE_WIDTH, 2); + break; + case 10000: + adp5585->reset_cfg |= FIELD_PREP(ADP5585_PULSE_WIDTH, 3); + break; + default: + return dev_err_probe(dev, -EINVAL, + "Invalid value(%u) for adi,reset-pulse-width-us\n", + prop_val); + } + } + + return 0; +} + +static int adp5585_parse_fw(struct device *dev, struct adp5585_dev *adp5585) +{ + const struct adp5585_info *info = adp5585->info; + unsigned int n_pins = info->max_cols + info->max_rows; + unsigned int *keypad_pins; + unsigned int prop_val; + int n_keys, key, ret; + + adp5585->keypad = devm_bitmap_zalloc(dev, n_pins, GFP_KERNEL); + if (!adp5585->keypad) + return -ENOMEM; + + if (device_property_present(dev, "#pwm-cells")) + adp5585->has_pwm = true; + + n_keys = device_property_count_u32(dev, "adi,keypad-pins"); + if (n_keys <= 0) + goto no_keypad; + if (n_keys > n_pins) + return -EINVAL; + + keypad_pins = devm_kcalloc(dev, n_keys, sizeof(*keypad_pins), + GFP_KERNEL); + if (!keypad_pins) + return -ENOMEM; + + ret = device_property_read_u32_array(dev, "adi,keypad-pins", + keypad_pins, n_keys); + if (ret) + return ret; + + for (key = 0; key < n_keys; key++) { + if (keypad_pins[key] >= n_pins) + return -EINVAL; + if (adp5585->has_pwm && keypad_pins[key] == ADP5585_ROW3) + return dev_err_probe(dev, -EINVAL, + "Invalid PWM pin being used in the keypad\n"); + if (!info->has_row5 && keypad_pins[key] == ADP5585_ROW5) + return dev_err_probe(dev, -EINVAL, + "Invalid row5 being used in the keypad\n"); + __set_bit(keypad_pins[key], adp5585->keypad); + } + +no_keypad: + ret = device_property_read_u32(dev, "adi,key-poll-ms", &prop_val); + if (!ret) { + switch (prop_val) { + case 10: + fallthrough; + case 20: + fallthrough; + case 30: + fallthrough; + case 40: + adp5585->key_poll_time = prop_val / 10 - 1; + break; + default: + return dev_err_probe(dev, -EINVAL, + "Invalid value(%u) for adi,key-poll-ms\n", + prop_val); + } + } + + ret = adp5585_keys_unlock_parse(adp5585); + if (ret) + return ret; + + return adp5585_keys_reset_parse(adp5585); +} + +static void adp5585_report_events(struct adp5585_dev *adp5585, int ev_cnt) +{ + unsigned int i; + + guard(mutex)(&adp5585->ev_lock); + + for (i = 0; i < ev_cnt; i++) { + unsigned int key, key_val, key_press; + int ret; + + ret = regmap_read(adp5585->regmap, ADP5585_FIFO_1 + i, &key); + if (ret) + return; + + key_val = FIELD_GET(ADP5585_KEY_EVENT_MASK, key); + key_press = FIELD_GET(ADP5585_KEV_EV_PRESS_MASK, key); + + if (key_val >= adp5585->info->gpi_ev_base && + key_val <= adp5585->info->gpi_ev_end) { + unsigned int gpi = key_val - adp5585->info->gpi_ev_base; + + if (adp5585->gpio_irq_handle) + adp5585->gpio_irq_handle(adp5585->gpio_dev, gpi, + key_press); + } else if (adp5585->keys_irq_handle) { + adp5585->keys_irq_handle(adp5585->input_dev, key_val, + key_press); + } + } +} + +static irqreturn_t adp5585_irq(int irq, void *data) +{ + struct adp5585_dev *adp5585 = data; + unsigned int status, ev_cnt; + int ret; + + ret = regmap_read(adp5585->regmap, ADP5585_INT_STATUS, &status); + if (ret) + return IRQ_HANDLED; + + if (status & ADP5585_OVRFLOW_INT) + dev_err_ratelimited(adp5585->dev, "Event Overflow Error\n"); + + if (!(status & ADP5585_EVENT_INT)) + goto out_irq; + + ret = regmap_read(adp5585->regmap, ADP5585_STATUS, &ev_cnt); + if (ret) + goto out_irq; + + ev_cnt = FIELD_GET(ADP5585_EC_MASK, ev_cnt); + if (!ev_cnt) + goto out_irq; + + adp5585_report_events(adp5585, ev_cnt); +out_irq: + regmap_write(adp5585->regmap, ADP5585_INT_STATUS, status); + return IRQ_HANDLED; +} + static void adp5585_osc_disable(void *data) { const struct adp5585_dev *adp5585 = data; @@ -303,6 +706,128 @@ static void adp5585_osc_disable(void *data) regmap_write(adp5585->regmap, ADP5585_GENERAL_CFG, 0); } +static int adp5585_setup(struct adp5585_dev *adp5585) +{ + const struct adp5585_regs *regs = adp5585->info->regs; + unsigned int reg_val, i; + int ret; + + for (i = 0; i < adp5585->nkeys_unlock; i++) { + ret = regmap_write(adp5585->regmap, ADP5589_UNLOCK1 + i, + adp5585->unlock_keys[i] | ADP5589_UNLOCK_EV_PRESS); + if (ret) + return ret; + } + + if (adp5585->nkeys_unlock) { + ret = regmap_update_bits(adp5585->regmap, ADP5589_UNLOCK_TIMERS, + ADP5589_UNLOCK_TIMER, + adp5585->unlock_time); + if (ret) + return ret; + + ret = regmap_set_bits(adp5585->regmap, ADP5589_LOCK_CFG, + ADP5589_LOCK_EN); + if (ret) + return ret; + } + + for (i = 0; i < adp5585->nkeys_reset1; i++) { + ret = regmap_write(adp5585->regmap, regs->reset1_event_a + i, + adp5585->reset1_keys[i] | ADP5585_RESET_EV_PRESS); + if (ret) + return ret; + } + + for (i = 0; i < adp5585->nkeys_reset2; i++) { + ret = regmap_write(adp5585->regmap, regs->reset2_event_a + i, + adp5585->reset2_keys[i] | ADP5585_RESET_EV_PRESS); + if (ret) + return ret; + } + + if (adp5585->nkeys_reset1 || adp5585->nkeys_reset2) { + ret = regmap_write(adp5585->regmap, regs->reset_cfg, + adp5585->reset_cfg); + if (ret) + return ret; + + reg_val = 0; + if (adp5585->nkeys_reset1) + reg_val = ADP5585_R4_EXTEND_CFG_RESET1; + if (adp5585->nkeys_reset2) + reg_val |= ADP5585_C4_EXTEND_CFG_RESET2; + + ret = regmap_update_bits(adp5585->regmap, regs->ext_cfg, + ADP5585_C4_EXTEND_CFG_MASK | + ADP5585_R4_EXTEND_CFG_MASK, + reg_val); + if (ret) + return ret; + } + + for (i = 0; i < ADP5585_EV_MAX; i++) { + ret = regmap_read(adp5585->regmap, ADP5585_FIFO_1 + i, + ®_val); + if (ret) + return ret; + } + + ret = regmap_write(adp5585->regmap, regs->poll_ptime_cfg, + adp5585->key_poll_time); + if (ret) + return ret; + + ret = regmap_write(adp5585->regmap, regs->gen_cfg, + ADP5585_OSC_FREQ_500KHZ | ADP5585_INT_CFG | + ADP5585_OSC_EN); + if (ret) + return ret; + + return devm_add_action_or_reset(adp5585->dev, adp5585_osc_disable, + adp5585); +} + +static void adp5585_irq_disable(void *data) +{ + struct adp5585_dev *adp5585 = data; + + regmap_write(adp5585->regmap, adp5585->info->regs->int_en, 0); +} + +static int adp5585_irq_enable(struct i2c_client *i2c, + struct adp5585_dev *adp5585) +{ + const struct adp5585_regs *regs = adp5585->info->regs; + unsigned int stat; + int ret; + + if (i2c->irq <= 0) + return 0; + + ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, adp5585_irq, + IRQF_ONESHOT, i2c->name, adp5585); + if (ret) + return ret; + + /* clear any possible outstanding interrupt before enabling them... */ + ret = regmap_read(adp5585->regmap, ADP5585_INT_STATUS, &stat); + if (ret) + return ret; + + ret = regmap_write(adp5585->regmap, ADP5585_INT_STATUS, stat); + if (ret) + return ret; + + ret = regmap_write(adp5585->regmap, regs->int_en, + ADP5585_OVRFLOW_IEN | ADP5585_EVENT_IEN); + if (ret) + return ret; + + return devm_add_action_or_reset(&i2c->dev, adp5585_irq_disable, + adp5585); +} + static int adp5585_i2c_probe(struct i2c_client *i2c) { const struct adp5585_info *info; @@ -321,6 +846,8 @@ static int adp5585_i2c_probe(struct i2c_client *i2c) return -ENODEV; adp5585->info = info; + adp5585->dev = &i2c->dev; + adp5585->irq = i2c->irq; adp5585->regmap = devm_regmap_init_i2c(i2c, info->regmap_config); if (IS_ERR(adp5585->regmap)) @@ -337,12 +864,15 @@ static int adp5585_i2c_probe(struct i2c_client *i2c) return dev_err_probe(&i2c->dev, -ENODEV, "Invalid device ID 0x%02x\n", id); - ret = regmap_set_bits(adp5585->regmap, ADP5585_GENERAL_CFG, - ADP5585_OSC_EN); + ret = adp5585_parse_fw(&i2c->dev, adp5585); if (ret) return ret; - ret = devm_add_action_or_reset(&i2c->dev, adp5585_osc_disable, adp5585); + ret = adp5585_setup(adp5585); + if (ret) + return ret; + + ret = devm_mutex_init(&i2c->dev, &adp5585->ev_lock); if (ret) return ret; @@ -353,13 +883,16 @@ static int adp5585_i2c_probe(struct i2c_client *i2c) return dev_err_probe(&i2c->dev, ret, "Failed to add child devices\n"); - return 0; + return adp5585_irq_enable(i2c, adp5585); } static int adp5585_suspend(struct device *dev) { struct adp5585_dev *adp5585 = dev_get_drvdata(dev); + if (adp5585->irq) + disable_irq(adp5585->irq); + regcache_cache_only(adp5585->regmap, true); return 0; @@ -368,11 +901,19 @@ static int adp5585_suspend(struct device *dev) static int adp5585_resume(struct device *dev) { struct adp5585_dev *adp5585 = dev_get_drvdata(dev); + int ret; regcache_cache_only(adp5585->regmap, false); regcache_mark_dirty(adp5585->regmap); - return regcache_sync(adp5585->regmap); + ret = regcache_sync(adp5585->regmap); + if (ret) + return ret; + + if (adp5585->irq) + enable_irq(adp5585->irq); + + return 0; } static DEFINE_SIMPLE_DEV_PM_OPS(adp5585_pm, adp5585_suspend, adp5585_resume); diff --git a/include/linux/mfd/adp5585.h b/include/linux/mfd/adp5585.h index dffe1449de01dacf8fe78cf0e87d1f176d11f620..3ec542bed9c1c44899cc869d957557813e2d0aab 100644 --- a/include/linux/mfd/adp5585.h +++ b/include/linux/mfd/adp5585.h @@ -10,13 +10,21 @@ #define __MFD_ADP5585_H_ #include +#include +#include #define ADP5585_ID 0x00 #define ADP5585_MAN_ID_VALUE 0x20 #define ADP5585_MAN_ID_MASK GENMASK(7, 4) +#define ADP5585_REV_ID_MASK GENMASK(3, 0) #define ADP5585_INT_STATUS 0x01 +#define ADP5585_OVRFLOW_INT BIT(2) +#define ADP5585_EVENT_INT BIT(0) #define ADP5585_STATUS 0x02 +#define ADP5585_EC_MASK GENMASK(4, 0) #define ADP5585_FIFO_1 0x03 +#define ADP5585_KEV_EV_PRESS_MASK BIT(7) +#define ADP5585_KEY_EVENT_MASK GENMASK(6, 0) #define ADP5585_FIFO_2 0x04 #define ADP5585_FIFO_3 0x05 #define ADP5585_FIFO_4 0x06 @@ -32,6 +40,7 @@ #define ADP5585_FIFO_14 0x10 #define ADP5585_FIFO_15 0x11 #define ADP5585_FIFO_16 0x12 +#define ADP5585_EV_MAX (ADP5585_FIFO_16 - ADP5585_FIFO_1 + 1) #define ADP5585_GPI_INT_STAT_A 0x13 #define ADP5585_GPI_INT_STAT_B 0x14 #define ADP5585_GPI_STATUS_A 0x15 @@ -60,6 +69,7 @@ #define ADP5585_GPIO_DIRECTION_A 0x27 #define ADP5585_GPIO_DIRECTION_B 0x28 #define ADP5585_RESET1_EVENT_A 0x29 +#define ADP5585_RESET_EV_PRESS BIT(7) #define ADP5585_RESET1_EVENT_B 0x2a #define ADP5585_RESET1_EVENT_C 0x2b #define ADP5585_RESET2_EVENT_A 0x2c @@ -104,8 +114,17 @@ #define ADP5585_INT_CFG BIT(1) #define ADP5585_RST_CFG BIT(0) #define ADP5585_INT_EN 0x3c +#define ADP5585_OVRFLOW_IEN BIT(2) +#define ADP5585_EVENT_IEN BIT(0) #define ADP5585_MAX_REG ADP5585_INT_EN +#define ADP5585_ROW3 3 +#define ADP5585_ROW4 4 +#define ADP5585_ROW5 5 +#define ADP5585_COL4 4 +#define ADP5585_MAX_UNLOCK_TIME_SEC 7 +#define ADP5585_GPI_EVENT_START 37 +#define ADP5585_GPI_EVENT_END 47 #define ADP5585_MAX_ROW_NUM 6 #define ADP5585_MAX_COL_NUM 5 @@ -124,18 +143,38 @@ #define ADP5589_GPI_STATUS_A 0x16 #define ADP5589_GPI_STATUS_C 0x18 #define ADP5589_RPULL_CONFIG_A 0x19 +#define ADP5589_GPI_INT_LEVEL_A 0x1e +#define ADP5589_GPI_EVENT_EN_A 0x21 #define ADP5589_DEBOUNCE_DIS_A 0x27 #define ADP5589_GPO_DATA_OUT_A 0x2a #define ADP5589_GPO_OUT_MODE_A 0x2d #define ADP5589_GPIO_DIRECTION_A 0x30 +#define ADP5589_UNLOCK1 0x33 +#define ADP5589_UNLOCK_EV_PRESS BIT(7) +#define ADP5589_UNLOCK_TIMERS 0x36 +#define ADP5589_UNLOCK_TIMER GENMASK(2, 0) +#define ADP5589_LOCK_CFG 0x37 +#define ADP5589_LOCK_EN BIT(0) +#define ADP5589_RESET1_EVENT_A 0x38 +#define ADP5589_RESET2_EVENT_A 0x3B +#define ADP5589_RESET_CFG 0x3D +#define ADP5585_RESET2_POL BIT(7) +#define ADP5585_RESET1_POL BIT(6) +#define ADP5585_RST_PASSTHRU_EN BIT(5) +#define ADP5585_RESET_TRIG_TIME GENMASK(4, 2) +#define ADP5585_PULSE_WIDTH GENMASK(1, 0) #define ADP5589_PWM_OFFT_LOW 0x3e #define ADP5589_PWM_ONT_LOW 0x40 #define ADP5589_PWM_CFG 0x42 +#define ADP5589_POLL_PTIME_CFG 0x48 +#define ADP5589_PIN_CONFIG_A 0x49 #define ADP5589_PIN_CONFIG_D 0x4C #define ADP5589_GENERAL_CFG 0x4d #define ADP5589_INT_EN 0x4e #define ADP5589_MAX_REG ADP5589_INT_EN +#define ADP5589_GPI_EVENT_START 97 +#define ADP5589_GPI_EVENT_END 115 #define ADP5589_MAX_ROW_NUM 8 #define ADP5589_MAX_COL_NUM 11 @@ -154,11 +193,19 @@ struct adp5585_regs { unsigned int gpo_out_a; unsigned int gpio_dir_a; unsigned int gpi_stat_a; + unsigned int gpi_ev_a; + unsigned int gpi_int_lvl_a; unsigned int pwm_cfg; unsigned int pwm_offt_low; unsigned int pwm_ont_low; + unsigned int reset_cfg; unsigned int gen_cfg; unsigned int ext_cfg; + unsigned int pin_cfg_a; + unsigned int poll_ptime_cfg; + unsigned int int_en; + unsigned int reset1_event_a; + unsigned int reset2_event_a; }; struct adp5585_info { @@ -169,6 +216,10 @@ struct adp5585_info { unsigned int id; u8 max_rows; u8 max_cols; + u8 gpi_ev_base; + u8 gpi_ev_end; + bool has_row5; + bool has_unlock; }; struct regmap; @@ -176,6 +227,51 @@ struct regmap; struct adp5585_dev { struct regmap *regmap; const struct adp5585_info *info; + struct device *dev; + unsigned long *keypad; + void (*gpio_irq_handle)(struct device *dev, unsigned int off, + bool key_press); + struct device *gpio_dev; + void (*keys_irq_handle)(struct device *dev, unsigned int off, + bool key_press); + struct device *input_dev; + /* + * Used to synchronize usage (and availability) of gpio_irq_handle() + * and keys_irq_handle(). + */ + struct mutex ev_lock; + int irq; + u32 key_poll_time; + u32 unlock_time; + u32 unlock_keys[2]; + u32 nkeys_unlock; + u32 reset1_keys[3]; + u32 nkeys_reset1; + u32 reset2_keys[2]; + u32 nkeys_reset2; + u8 reset_cfg; + bool has_pwm; }; +static inline void adp5585_gpio_ev_handle_set(struct adp5585_dev *adp5585, + void (*handle)(struct device *dev, + unsigned int off, + bool key_press), + struct device *gpio_dev) +{ + guard(mutex)(&adp5585->ev_lock); + adp5585->gpio_irq_handle = handle; + adp5585->gpio_dev = gpio_dev; +} + +static inline void adp5585_keys_ev_handle_set(struct adp5585_dev *adp5585, + void (*handle)(struct device *dev, + unsigned int off, + bool key_press), + struct device *input_dev) +{ + guard(mutex)(&adp5585->ev_lock); + adp5585->keys_irq_handle = handle; + adp5585->input_dev = input_dev; +} #endif From patchwork Tue Apr 15 14:49:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= X-Patchwork-Id: 881485 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9BC0E29C344; Tue, 15 Apr 2025 14:49:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728560; cv=none; b=ElIyXLznPQZveyfkj9xwc/Oks2KdriN+9O6V7sTZeMDkhsX7K/cbPhLt9tNhuB3BlGZXRxBY3r4fYm/jvmbh7i8c4CKzZTtTg8NJa38zgg2XrlQciMDEq0seNjYXGX1XuWVQNjsuWABCcXTifZPcyFVVEiy7CUJEytrCXPVflBg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728560; c=relaxed/simple; bh=iVhgU6oV67ih93tinGJIsjkoppOG74W/wQwnUiQILTc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=YPHBb3nWcHTzZBpu1RrArsfbWfBW4+wnsfJsA9C1kknXmlYPOD8C4tew4/19OvTyEvHpaq5XR4jXdSQ9vPh3QJ8yQ6CpEmaWfB1FJf+bHmz8UxuyDSsoVvHL0RqD3KN83b7WDFW6w5N4YxILYs6SmPLrhvWqfUjqLDfuenPsHdA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pfeGtB6g; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="pfeGtB6g" Received: by smtp.kernel.org (Postfix) with ESMTPS id DB49DC4AF55; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744728560; bh=iVhgU6oV67ih93tinGJIsjkoppOG74W/wQwnUiQILTc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=pfeGtB6gk6IsfWPp7d9uQnWQBO8EAFEj6QsSKn9Ic2ir02KMcj8rg10FRrXiuKUHx tABbDwGS1+PZJBz1XXmDGDdllCqEc0VsgBo/Le586DkGZxmtPmQD1bqnrdRnY1ljWj 7WTXbIitfrE1OJjtrciHUcUxcDbh7qq7ztsrmgLJ0pusXhw0qRAQZzshyakS1k6GTi pWb0qLwoJUNyXB0MTFWDMVQOtSiz+NDAZYuN4bQEr1GBUYE7hEL9ymS/kFprr2qXWb ou73T3A4MvdozgDdWL9s8238paoGgxI0QJc57vabuOWxzTkmhuqnCZUlY7OH7q8ke9 Djpr5Z+yp1XLQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id D1840C369C1; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Tue, 15 Apr 2025 15:49:28 +0100 Subject: [PATCH v2 12/17] Input: adp5585: Add Analog Devices ADP5585/89 support Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250415-dev-adp5589-fw-v2-12-3a799c3ed812@analog.com> References: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> In-Reply-To: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> To: linux-gpio@vger.kernel.org, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-input@vger.kernel.org Cc: Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Linus Walleij , Bartosz Golaszewski , Dmitry Torokhov , Laurent Pinchart , Liu Ying X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1744728560; l=9142; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=JrfKluLxDKtg4bj+oFHP0M300253piXuwv6kEF5DBpM=; b=COQk4keBOrfSXZhqmDZeHBwztsNoMNCCeFzExrYBgEucNIgly5MDsYz+f0Fn12/AvoOopW9QE ADUzuYSgHcoCzlePOj/KQ9BJEKsTBy6P03RtiI/JjfepwyzHJqV/F4y X-Developer-Key: i=nuno.sa@analog.com; a=ed25519; pk=3NQwYA013OUYZsmDFBf8rmyyr5iQlxV/9H4/Df83o1E= X-Endpoint-Received: by B4 Relay for nuno.sa@analog.com/20231116 with auth_id=100 X-Original-From: =?utf-8?q?Nuno_S=C3=A1?= Reply-To: nuno.sa@analog.com From: Nuno Sá The ADP5585 is a 10/11 input/output port expander with a built in keypad matrix decoder, programmable logic, reset generator, and PWM generator. This driver supports the keyboard function using the platform device registered by the core MFD driver. The ADP5589 has 19 pins and also features an unlock function. Signed-off-by: Nuno Sá --- MAINTAINERS | 1 + drivers/input/keyboard/Kconfig | 11 ++ drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/adp5585-keys.c | 221 ++++++++++++++++++++++++++++++++++ 4 files changed, 234 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index b5acf50fc6af4322dec0dad2169b46c6a1903e3c..48bd39a1a96d9c57145cf2560eec54248427fc89 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -549,6 +549,7 @@ L: linux-pwm@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/*/adi,adp5585*.yaml F: drivers/gpio/gpio-adp5585.c +F: drivers/input/adp5585-keys.c F: drivers/mfd/adp5585.c F: drivers/pwm/pwm-adp5585.c F: include/linux/mfd/adp5585.h diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 721ab69e84ac6586f4f19102890a15ca3fcf1910..322da0957067db77c7f66ab26a181d39c2c1d513 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -37,6 +37,17 @@ config KEYBOARD_ADP5520 To compile this driver as a module, choose M here: the module will be called adp5520-keys. +config KEYBOARD_ADP5585 + tristate "ADP5585 and similar I2C QWERTY Keypad and IO Expanders" + depends on MFD_ADP5585 + select INPUT_MATRIXKMAP + help + This option enables support for the KEYMAP function found in the Analog + Devices ADP5585 and similar devices. + + To compile this driver as a module, choose M here: the + module will be called adp5585-keys. + config KEYBOARD_ADP5588 tristate "ADP5588/87 I2C QWERTY Keypad and IO Expander" depends on I2C diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 1e0721c3070968a6339a42f65a95af48364f6897..f00ec003a59aa28577ae164c0539cc5aff9579fc 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_KEYBOARD_ADC) += adc-keys.o obj-$(CONFIG_KEYBOARD_ADP5520) += adp5520-keys.o +obj-$(CONFIG_KEYBOARD_ADP5585) += adp5585-keys.o obj-$(CONFIG_KEYBOARD_ADP5588) += adp5588-keys.o obj-$(CONFIG_KEYBOARD_ADP5589) += adp5589-keys.o obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o diff --git a/drivers/input/keyboard/adp5585-keys.c b/drivers/input/keyboard/adp5585-keys.c new file mode 100644 index 0000000000000000000000000000000000000000..93961a9e822f8b10b1bca526b9486eed4ad7f8f7 --- /dev/null +++ b/drivers/input/keyboard/adp5585-keys.c @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Analog Devices ADP5585 Keys driver + * + * Copyright (C) 2025 Analog Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* As needed for the matrix parsing code */ +#define ADP5589_MAX_KEYMAPSIZE 123 + +struct adp5585_kpad { + struct input_dev *input; + unsigned short keycode[ADP5589_MAX_KEYMAPSIZE]; + struct device *dev; + int row_shift; + u8 max_rows; + u8 max_cols; +}; + +static int adp5585_keys_parse_fw(const struct adp5585_dev *adp5585, + struct adp5585_kpad *kpad) +{ + unsigned long row_map, col_map; + struct device *dev = kpad->dev; + u32 cols = 0, rows = 0; + int ret; + + row_map = bitmap_read(adp5585->keypad, 0, kpad->max_rows); + col_map = bitmap_read(adp5585->keypad, kpad->max_rows, kpad->max_cols); + /* + * Note that given that we get a mask (and the HW allows it), we + * can have holes in our keypad (eg: row0, row1 and row7 enabled). + * However, for the matrix parsing functions we need to pass the + * number of rows/cols as the maximum row/col used plus 1. This + * pretty much means we will also have holes in our SW keypad. + */ + if (!bitmap_empty(&row_map, kpad->max_rows)) + rows = find_last_bit(&row_map, kpad->max_rows) + 1; + if (!bitmap_empty(&col_map, kpad->max_cols)) + cols = find_last_bit(&col_map, kpad->max_cols) + 1; + + if (!rows && !cols) + return dev_err_probe(dev, -EINVAL, + "No rows or columns defined for the keypad\n"); + + if (cols && !rows) + return dev_err_probe(dev, -EINVAL, + "Cannot have columns with no rows!\n"); + + if (rows && !cols) + return dev_err_probe(dev, -EINVAL, + "Cannot have rows with no columns!\n"); + + ret = matrix_keypad_build_keymap(NULL, NULL, rows, cols, + kpad->keycode, kpad->input); + if (ret) + return ret; + + kpad->row_shift = get_count_order(cols); + + if (device_property_present(kpad->dev, "autorepeat")) + __set_bit(EV_REP, kpad->input->evbit); + + return 0; +} + +static int adp5585_keys_setup(const struct adp5585_dev *adp5585, + struct adp5585_kpad *kpad) +{ + unsigned long keys_bits, start = 0, nbits = kpad->max_rows; + const struct adp5585_regs *regs = adp5585->info->regs; + unsigned int i = 0, max_cols = kpad->max_cols; + int ret; + + /* + * Take care as the below assumes max_rows is always less or equal than + * 8 which is true for the supported devices. If we happen to add + * another device we need to make sure this still holds true. Although + * adding a new device is very unlikely. + */ + do { + keys_bits = bitmap_read(adp5585->keypad, start, nbits); + if (keys_bits) { + ret = regmap_write(adp5585->regmap, regs->pin_cfg_a + i, + keys_bits); + if (ret) + return ret; + } + + start += nbits; + if (max_cols > 8) { + nbits = 8; + max_cols -= nbits; + } else { + nbits = max_cols; + } + + i++; + } while (start < kpad->max_rows + kpad->max_cols); + + return 0; +} + +static void adp5585_keys_ev_handle(struct device *dev, unsigned int key, + bool key_press) +{ + struct adp5585_kpad *kpad = dev_get_drvdata(dev); + unsigned int row, col, code; + + row = (key - 1) / (kpad->max_cols); + col = (key - 1) % (kpad->max_cols); + code = MATRIX_SCAN_CODE(row, col, kpad->row_shift); + + dev_dbg_ratelimited(kpad->dev, "report key(%d) r(%d) c(%d) code(%d)\n", + key, row, col, kpad->keycode[code]); + + input_report_key(kpad->input, kpad->keycode[code], key_press); + input_sync(kpad->input); +} + +static void adp5585_keys_ev_handle_clean(void *adp5585) +{ + adp5585_keys_ev_handle_set(adp5585, NULL, NULL); +} + +static int adp5585_keys_probe(struct platform_device *pdev) +{ + struct adp5585_dev *adp5585 = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + struct adp5585_kpad *kpad; + unsigned int revid; + const char *phys; + int ret; + + kpad = devm_kzalloc(dev, sizeof(*kpad), GFP_KERNEL); + if (!kpad) + return -ENOMEM; + + if (!adp5585->irq) + return dev_err_probe(dev, -EINVAL, + "IRQ is mandatory for the keypad\n"); + + kpad->dev = dev; + kpad->max_cols = adp5585->info->max_cols; + kpad->max_rows = adp5585->info->max_rows; + + kpad->input = devm_input_allocate_device(dev); + if (!kpad->input) + return -ENOMEM; + + ret = regmap_read(adp5585->regmap, ADP5585_ID, &revid); + if (ret) + return dev_err_probe(dev, ret, "Failed to read device ID\n"); + + phys = devm_kasprintf(dev, GFP_KERNEL, "%s/input0", pdev->name); + if (!phys) + return -ENOMEM; + + kpad->input->name = pdev->name; + kpad->input->phys = phys; + kpad->input->dev.parent = dev; + + input_set_drvdata(kpad->input, kpad); + + kpad->input->id.bustype = BUS_I2C; + kpad->input->id.vendor = 0x0001; + kpad->input->id.product = 0x0001; + kpad->input->id.version = revid & ADP5585_REV_ID_MASK; + + device_set_of_node_from_dev(dev, dev->parent); + + ret = adp5585_keys_parse_fw(adp5585, kpad); + if (ret) + return ret; + + ret = adp5585_keys_setup(adp5585, kpad); + if (ret) + return ret; + + platform_set_drvdata(pdev, kpad); + adp5585_keys_ev_handle_set(adp5585, adp5585_keys_ev_handle, dev); + ret = devm_add_action_or_reset(dev, adp5585_keys_ev_handle_clean, + adp5585); + if (ret) + return ret; + + return input_register_device(kpad->input); +} + +static const struct platform_device_id adp5585_keys_id_table[] = { + { "adp5585-keys" }, + { "adp5589-keys" }, + { } +}; +MODULE_DEVICE_TABLE(platform, adp5585_keys_id_table); + +static struct platform_driver adp5585_keys_driver = { + .driver = { + .name = "adp5585-keys", + }, + .probe = adp5585_keys_probe, + .id_table = adp5585_keys_id_table, +}; +module_platform_driver(adp5585_keys_driver); + +MODULE_AUTHOR("Nuno Sá "); +MODULE_DESCRIPTION("ADP5585 Keys Driver"); +MODULE_LICENSE("GPL"); From patchwork Tue Apr 15 14:49:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= X-Patchwork-Id: 881484 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BA53329DB80; Tue, 15 Apr 2025 14:49:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728560; cv=none; b=lnbrVxWkajl0ljXBcMdO7lyJmp33IH0m0cig1RD0C8/hwCf4CTI+QJglIo+YvHHvlgVwArWQEaWlgb8hTKzwePCT4lHwAjT2HZomF504ahd/XTY/0m4j4jWVwe2sWCuW8CgTLz4pm+qgM8SnxxNZG1KsfKIs3d2Otbk4XkD80cA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728560; c=relaxed/simple; bh=m52txbV845I26abToavpRxXAGj6iKqZnKmxudw++b60=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ocpj27CR1hirlxssfk0P+EheevUi5FIsDhh1InYZKLwj7R8KWIcDMunFYJ42pdXjgSquFQBkt/a1DEvCBiYwUqLk7qbHinFQUKmIxNfJmzNUewGlK84GIMjfr/5Um2uM7YrgBEe86WFCQ6Tk2WWD/kP90By7tBoVzR7jR3/GdZM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RJ+2r6tC; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="RJ+2r6tC" Received: by smtp.kernel.org (Postfix) with ESMTPS id 09BEFC2BCB0; Tue, 15 Apr 2025 14:49:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744728560; bh=m52txbV845I26abToavpRxXAGj6iKqZnKmxudw++b60=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=RJ+2r6tCJEZy9IngLYw8MAuCbTxWClrkq6IPCTZ6E4XxbYPrnZpsHYzIQWJK1ykHJ bpZuRy4HxPSbd22SoYkgXIeOQZenGYYBD6UOEqdN5Ms/9X47P7o/EiSiew1SQkQRPy FPNuabx9gjpIitEDNp64SAbCGlNOzCZTRBiBUg2f5oDR8WAAwmNQ+adASEJgaI4UZU BmK4dYxU+8+0XSHoSRw5lA7L3hKGHjU181TU3wx3VEB/eIUvHsX8ch6Qgs34d0arO3 eBOKBESRPXj6SjRZFpI69UxyUKfCK/y7oySKYfmHO6utJY/UQGg3cf0PPNtR+knR2D tf9GRHNKURLZg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id F1D8BC369BD; Tue, 15 Apr 2025 14:49:19 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Tue, 15 Apr 2025 15:49:30 +0100 Subject: [PATCH v2 14/17] mfd: adp5585: support getting vdd regulator Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250415-dev-adp5589-fw-v2-14-3a799c3ed812@analog.com> References: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> In-Reply-To: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> To: linux-gpio@vger.kernel.org, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-input@vger.kernel.org Cc: Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Linus Walleij , Bartosz Golaszewski , Dmitry Torokhov , Laurent Pinchart , Liu Ying X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1744728560; l=1028; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=PMNgdya0dxZ43x5DB45Njbna7Ac70vPeST9gjKhIiIY=; b=cXirkJFBAXlczFnI9vdLwWMcetge5QyFstRgH1DI1QK0wN5klqFLjSeewAAhlfO+uNG4WiN4Q 8c39Pj4pQV0DXz/TIiAWpQWq1C1PYpsO7uVHyGPRC1eqBjwMg65Ujuu X-Developer-Key: i=nuno.sa@analog.com; a=ed25519; pk=3NQwYA013OUYZsmDFBf8rmyyr5iQlxV/9H4/Df83o1E= X-Endpoint-Received: by B4 Relay for nuno.sa@analog.com/20231116 with auth_id=100 X-Original-From: =?utf-8?q?Nuno_S=C3=A1?= Reply-To: nuno.sa@analog.com From: Nuno Sá Make sure we get and enable the VDD supply (if available). Signed-off-by: Nuno Sá --- drivers/mfd/adp5585.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mfd/adp5585.c b/drivers/mfd/adp5585.c index c1d51d50dca6c9367d4a1b98a4f8bbec12dbf90b..667cc5bd0745f64eec60837ec3c00057af0cddeb 100644 --- a/drivers/mfd/adp5585.c +++ b/drivers/mfd/adp5585.c @@ -18,6 +18,7 @@ #include #include #include +#include #include static const struct mfd_cell adp5585_devs[] = { @@ -849,6 +850,10 @@ static int adp5585_i2c_probe(struct i2c_client *i2c) adp5585->dev = &i2c->dev; adp5585->irq = i2c->irq; + ret = devm_regulator_get_enable(&i2c->dev, "vdd"); + if (ret) + return ret; + adp5585->regmap = devm_regmap_init_i2c(i2c, info->regmap_config); if (IS_ERR(adp5585->regmap)) return dev_err_probe(&i2c->dev, PTR_ERR(adp5585->regmap), From patchwork Tue Apr 15 14:49:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= X-Patchwork-Id: 881483 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D7EF929B76D; Tue, 15 Apr 2025 14:49:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728561; cv=none; b=QlzWrnNWj576ORUgHnJ42oi+FAJQfS6ZkbkA6z27N8Q4sVnplbINB4qQJcUdhleNl17TuTjHPFhhcy5UeekUV61ZibASFm3FktOo7NzYtP1cISjcvRBkqX7baGjRaP4XeBeaBmVHR7GeChEEtp9eUmYRjKx17EyA10zTIGHohLU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744728561; c=relaxed/simple; bh=crsEGvz1m8k2FjNEc+Qy8b+aWznTQrDr7Qb+3QKD4yU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bBj071R6avOoZm8wm6xBDZmuZq2vMigORE1aat8xJOcxRUGTQFX+tPsQWOwpODaEh5edoZ7W+XDKtOrFS6ZAZaf3VrQHlrxewFIUSDlSJoXKeO/VfK1rPg2wKfulKWA5Vth2fWoK58dT6D9VXvK9rKFV1JHjHw8FTE2TBB2IR6E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hjF9XOWz; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hjF9XOWz" Received: by smtp.kernel.org (Postfix) with ESMTPS id 2DCA7C4CEEC; Tue, 15 Apr 2025 14:49:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1744728560; bh=crsEGvz1m8k2FjNEc+Qy8b+aWznTQrDr7Qb+3QKD4yU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=hjF9XOWz87zZMMTNp+OZjZpCipzINW54y244H2Gh6gP++GblJDkZ2FWWzoeF5nu5P hFvGZy8qCKoKBw/s2eWawNDRrW3cL5o15ZLUA8oRYlfSkdJB6ygEyNGVKQCLYTlLbz k2SdYs0rfeG8dHlmSw0iCI2i2/C8utRz7M7jQmfbiWHcWkKUacdDnq/5mXymaPkjAc fR7R4SHX4qPqt0ea/d1EHxt8bB13AICl8yhDLurz+1anp4L9J3+GQUnCVlaCQWguGs 4d/Jpu1nsf+FaJi6Gv1fpstKwI99C+DNh2oDDwTUskfeValco2m0btbYRFN5WxuLAQ neUMLELSGgeJg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1EC13C369C1; Tue, 15 Apr 2025 14:49:20 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Tue, 15 Apr 2025 15:49:32 +0100 Subject: [PATCH v2 16/17] mfd: adp5585: add support for a reset pin Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250415-dev-adp5589-fw-v2-16-3a799c3ed812@analog.com> References: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> In-Reply-To: <20250415-dev-adp5589-fw-v2-0-3a799c3ed812@analog.com> To: linux-gpio@vger.kernel.org, linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-input@vger.kernel.org Cc: Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Linus Walleij , Bartosz Golaszewski , Dmitry Torokhov , Laurent Pinchart , Liu Ying X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1744728560; l=1359; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=YXvB+ZSL0gZ4TQpg4/Gr7rz9RArZE2EGcmubpPAGy0c=; b=c7XdjNLWoVohdo+K7gcTPaJ5dYtAo7/Xwwh8fOzY6qtAOuLhu1jL12IQfKPYutOaaCRnsXoTA UoNtNj6O6TeBfW9lIip3xC+GP1YwGhi1nvj91grKr5LKet32SFr2rcd X-Developer-Key: i=nuno.sa@analog.com; a=ed25519; pk=3NQwYA013OUYZsmDFBf8rmyyr5iQlxV/9H4/Df83o1E= X-Endpoint-Received: by B4 Relay for nuno.sa@analog.com/20231116 with auth_id=100 X-Original-From: =?utf-8?q?Nuno_S=C3=A1?= Reply-To: nuno.sa@analog.com From: Nuno Sá Make sure to perform an Hardware reset during probe if the pin is given in FW. Signed-off-by: Nuno Sá --- drivers/mfd/adp5585.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/mfd/adp5585.c b/drivers/mfd/adp5585.c index 667cc5bd0745f64eec60837ec3c00057af0cddeb..2af110fb28054c8ad6709a9a42cb21919be433e7 100644 --- a/drivers/mfd/adp5585.c +++ b/drivers/mfd/adp5585.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -833,6 +834,7 @@ static int adp5585_i2c_probe(struct i2c_client *i2c) { const struct adp5585_info *info; struct adp5585_dev *adp5585; + struct gpio_desc *gpio; unsigned int id; int ret; @@ -854,6 +856,16 @@ static int adp5585_i2c_probe(struct i2c_client *i2c) if (ret) return ret; + gpio = devm_gpiod_get_optional(&i2c->dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(gpio)) + return PTR_ERR(gpio); + + if (gpio) { + fsleep(30); + gpiod_set_value_cansleep(gpio, 0); + fsleep(60); + } + adp5585->regmap = devm_regmap_init_i2c(i2c, info->regmap_config); if (IS_ERR(adp5585->regmap)) return dev_err_probe(&i2c->dev, PTR_ERR(adp5585->regmap),