From patchwork Thu Mar 13 14:19: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: 873654 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 E898E267F77; Thu, 13 Mar 2025 14:19:17 +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=1741875558; cv=none; b=NamOeId/PJGji1Y+DaL6A/wiay4592tsdSB205JG4h+GVotdXytZClPPjIEkYTDmgn73w7DIyeXCmIuqGlK0oQcon0JuODAkAMTPx3A/whLmWwQHMsP0krQFah2mtJRfkLW0ZSLah7spLM6I2E0KIEP4m0zOUJlS6UbyxcHg2uw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875558; c=relaxed/simple; bh=YtEjpGrReXVVOC7M4ZbCelu9IjfNeOo8tGBCnUi0BH8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=N48GomlTrgWUtpMq5ZvU7OTgqgKfI4teydM+vSb1ZeD5ILMIqSe/FcQs7GnC/4gDsmJkHlskBx+DlM7SL7uiMnv7OBJjsDlct0GRDiM66x0iXJ70txVjWpz/J0QoxuQ41AzG7AMCN5w9/6V4PBrQckJP24RdNV+BYscNHs+wBoQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SUTQpfwD; 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="SUTQpfwD" Received: by smtp.kernel.org (Postfix) with ESMTPS id 574B9C4CEEE; Thu, 13 Mar 2025 14:19:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875557; bh=YtEjpGrReXVVOC7M4ZbCelu9IjfNeOo8tGBCnUi0BH8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=SUTQpfwDbNDzFiovKEB+v6Rv/PxJEw6fewrqa0ygvA3ZRvsZq1chqrofFw9BVF9pt SpMRN/yg+G/I8O7wqbOJapEzzYVUl1qjbZNiz+Mdy4uXQ737oCGd4NQO3RXyc1zFlk 6aUIFEw70EJdIIaHQ2F/ibzPXpe0FnmJZe4UzlvCdE5ZxeNRxaGYIcwiXuSGpmscze ZWI+5/bhMypcP0fcnsLWQuoJokCHnIYbEfi7crYIdezowbzxx74odQrCDgMP4QrYqd Ks86sdhbJodGHwBuVRfJLcFaJ1/WDgf0MSrfGT7wKFl7DjCVOBldEu2g3G5JHoXjJH lun/9xaBuC1NQ== 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 45CE4C28B2E; Thu, 13 Mar 2025 14:19:17 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:18 +0000 Subject: [PATCH 01/18] dt-bindings: mfd: adp5585: ease on the required properties Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-1-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875561; l=940; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=T2atPfBGTb1TfWuyPCIna6CG+VGxW5uOUwbdmZcLmO4=; b=ZFI7u1RwR+07opm2Y9BPmSivWvT71+iT1KcQNPQIhduLd+InaybjhEAdsagJUZzaCZ+cuEjKN 0RyWCRQ4TIPBQgmmGMBNxBudwHOHwtj1YqTKbxOkREMVLMucW6L+9FE 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 Thu Mar 13 14:19:19 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: 873250 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 EA32B267F78; Thu, 13 Mar 2025 14:19:17 +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=1741875558; cv=none; b=O2N3qKlUAynMZQ2rDUGu+Iv3smWZ6OzEqeY6Byoad+ObvXSPahmpOiO+DCmMXjkF+h+YFqyCWskCnaaFABXc0KYxZlaLR48/AbKAw+79g4NMzSPLxJTUBTvQg7OFbfbAnRZbhgJ8OAQXlRTTbELap2lRoG944w6UwVmyB/q6m4o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875558; c=relaxed/simple; bh=21SH9HT66XncANfAaxmzWqMbDAWxv+aJKJgHdWpdK9w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VoiXIyh0Nqo68JWtzsAnYZeyh8y/COKuMVoSeyDdDa9CDA71e82I1qkshEvjgwvcpspYQU9TXfI0OhoTKTWadl1ctSwQFT7deP9yKwIJiaEVZKPfEEZ5tCxe0L25fVD6wVsVzHtJ9HCBlwvj1BaEJZAGe5muMDyb8QP+4LqANoU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ud7QVokA; 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="Ud7QVokA" Received: by smtp.kernel.org (Postfix) with ESMTPS id 6918CC4CEEA; Thu, 13 Mar 2025 14:19:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875557; bh=21SH9HT66XncANfAaxmzWqMbDAWxv+aJKJgHdWpdK9w=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Ud7QVokAl+/Geo9malXWHL78jFNvRPmRdXVNFZn/zpCj5IpAOzHuuPNwDxZ4Fgcxh W5WkGu7J0OakY6gWdHIF505eYZkGHRx+o6hIkpRvCaYD623umDmw9kvxum8U9oqEww 18XOJgR4L8pWV62PHxZN758c0Vc93diFDcrU4l4S3lcioKTZAQS+xblyAfNMPiQd9l vpfceBpDpodEwJmVd1Im/CpIgfzlx2Zi9LpJJY4KmiO1ahshMS50esmiS1lk5FhM9R RA/JW5xJXKFRGQoFPhsDkTpb0ndl1GcBcIsNtPtzVsoTkov13t76HV1GCSuOCrHNLO bIC28Qrw+vnRw== 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 55EF6C282DE; Thu, 13 Mar 2025 14:19:17 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:19 +0000 Subject: [PATCH 02/18] mfd: adp5585: enable oscilator during probe Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-2-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875561; l=1542; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=a2pyPe8f4gkDfJ4FYoI3t3mPu8zi6Gu5H6IP/tigIYM=; b=2Oif+I86b+7OgMwqAPYmM7wKY/LbkwBJsDk8R6jO6bxQMMsLIdOaNQ2A075rPxfITjlZtofma MC7MbGKZQWsAxrxT6Flf7u6yV9VppIIPZEp0Xow7tFmF3Tf0ycrCv8Y 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 Thu Mar 13 14:19:20 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: 873251 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 A1F652676E4; Thu, 13 Mar 2025 14:19:17 +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=1741875557; cv=none; b=cqG0Jic4BHcLnjig+7loHUqb0RFJplC4eRmDRfid/ConMwJznc/du50omLfp1F4rl7H2rt4Oysre7MnHyh3Ijcsdkq3OmIsrIMIP1jZAsQNmtsX2Lk6uKp4cN/8Z7yaz5LtGBHpn4NqdXyiTqYox+5XKkrLMtESxaDq9bIknte4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875557; c=relaxed/simple; bh=tfv/OEW5HX1cdoV3Bt6XmUwlf/25u+sSlJmK8/R/SL8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pJ1pOFGSU1oeJx8cHEMFaPvcI3M/sJRoeaKcBE0w67jr5BbfhGA+Oo23PRvU/7TITQ5/DgGyA7f+C9h7hytEJd/1jtxNcjkhTcsM1FLcuZFxLCcfhe822J3QW6YmBswEIt1Fi4aMuc+vhZcUv6ZfWUM47P2mjU5N4IuKbxqgNLw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=a4gSYMdV; 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="a4gSYMdV" Received: by smtp.kernel.org (Postfix) with ESMTPS id 74D37C4CEF1; Thu, 13 Mar 2025 14:19:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875557; bh=tfv/OEW5HX1cdoV3Bt6XmUwlf/25u+sSlJmK8/R/SL8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=a4gSYMdVZyamY5EtOkZ2Rf3GeiCU3UcyRk0+Z1QHeax+Q+sWBVdVhBs6EYDwxwgx0 XmQefz+JDtQ6VFtEt493bQvDxDMXNiy0wc/QmJKqs+sxPI6fETHHOeCx//Q3LrY6pj 2+kFzvwJrmVGfEKZgLvDOpSw8AgSU9ys3C1fuHipohB7KfCxHmLZnFR8+GOjvviMlr RSL5+WAZ0NzfdFhjKQ6VsEiDjXNdAphMpd1CjEFLXGBMS9S6W99d0uEOCGaRNkrPzS uAUboyOmI9JunZSvtRPZvi6rR7zLkWVwEqgYprhKvca8OmVorfK7W8Ctf8tOt+pfem KC6F5jaCgrfCA== 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 6AB4EC282EC; Thu, 13 Mar 2025 14:19:17 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:20 +0000 Subject: [PATCH 03/18] pwm: adp5585: don't control OSC_EN in the pwm driver Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-3-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875561; l=1401; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=NKMhcBbOgt50Ja7FHiyyQXPORjz4cMFleY53Owp+Grk=; b=oXdbhF25zDaKWCKrwdoGgenIXZn6RhFNXPlhcLlcEurnHGqEw08zMUzh6oK2xgY3mdL4VzkcW mIpfwjxqNFWAt6eIouSsCe6gPrLvTJ5EoKoeDHrKTqy1rkAp9/FPyu+ 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 Multi Function Device that can also be a gpio controller and as it turns out, when OSC_EN is not set, we can't reliably read the gpio value when it's configured as input. Hence, OSC_EN will be set during probe by the parent device (and cleared on unbind). Moreover, we'll add support for the keymap matrix (input device) which definitely needs OSC_EN to be set and so, we cannot afford that disabling the PWM output also breaks the keymap events generation. Signed-off-by: Nuno Sá --- drivers/pwm/pwm-adp5585.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/pwm/pwm-adp5585.c b/drivers/pwm/pwm-adp5585.c index 40472ac5db6410a33e4f790fe8e6c23b517502be..c8821035b7c1412a55a642e6e8a46b66e693a5af 100644 --- a/drivers/pwm/pwm-adp5585.c +++ b/drivers/pwm/pwm-adp5585.c @@ -62,7 +62,6 @@ static int pwm_adp5585_apply(struct pwm_chip *chip, int ret; if (!state->enabled) { - regmap_clear_bits(regmap, ADP5585_GENERAL_CFG, ADP5585_OSC_EN); regmap_clear_bits(regmap, ADP5585_PWM_CFG, ADP5585_PWM_EN); return 0; } @@ -100,10 +99,6 @@ static int pwm_adp5585_apply(struct pwm_chip *chip, if (ret) return ret; - ret = regmap_set_bits(regmap, ADP5585_GENERAL_CFG, ADP5585_OSC_EN); - if (ret) - return ret; - return regmap_set_bits(regmap, ADP5585_PWM_CFG, ADP5585_PWM_EN); } From patchwork Thu Mar 13 14:19: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: 873655 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 B1F5B267B85; Thu, 13 Mar 2025 14:19:17 +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=1741875557; cv=none; b=i9kZgM2BYvDpUv9fqy0/7sSQ8rgII8aqY/B9l5rN6ghJ8EF40Xg0lbsGsKLYTyoiMChjAplOGrp5d3E1q0KwFvxJSTZiEmqaXVx/rrFD3y8NSXtz7gWUTogSVe8tDRzEzCCSIKmIGvRmHNfc797B98VM1GOjp/uO6BA5CrbhlQM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875557; c=relaxed/simple; bh=L2j6c3iMZcaEN043NF199YD6t+IQz08DVL9/1v7GFyE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kYIrzzQ4ZLngiMkZ/OIZ5r4md51hlVVlR2M2x0csEod/RxGDh2x9HiQ2AQDXDoZ6z3B9yhxsId/Khx8Klosgyma5yVmgXcsNLQYDSoCiQhJ1GBrgQGz688ArR8ThKCuJPdSKTgpgzuLtxSwF9lNSxrFiXl7BAPWQXzha3Z83u+0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dBXrK3mZ; 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="dBXrK3mZ" Received: by smtp.kernel.org (Postfix) with ESMTPS id 83847C4CEF6; Thu, 13 Mar 2025 14:19:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875557; bh=L2j6c3iMZcaEN043NF199YD6t+IQz08DVL9/1v7GFyE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=dBXrK3mZ/sqGWQ/z4t6vE1kwphX9ACmWf5SDfSH9mCR36oxNdPxwcbPJvcP2ggULQ RxoMUVDEObbi2p7Y9uRmCWuIUbn2rr4hDP98qCeaoX7IQtuTrr09UYXpa6vJlHfVs/ 6rkTdpmqZcfldfCr1Em9K/pTExYFT1wNOq4ySrEdqulVMhDBecfo1mv66CnSXj6Q5H puTI8KkOAHjJtKHnPu/YGhWIT/ArM/lkTgEhA+dHq6XJDOYp8r6bHF+PHl9Jdzg9hi RDvtAL6b2yqWHWQ6KrHQal3v1QBSxpDsBPaKiCWXJXGoPGxDV+CFZQ+f/813ajL11L 4a4hyHQalBKMw== 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 7A749C28B2E; Thu, 13 Mar 2025 14:19:17 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:21 +0000 Subject: [PATCH 04/18] mfd: adp5585: make use of MFD_CELL_NAME() Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-4-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875561; l=932; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=+JLyImFSoRH3lvKr/gEYTk2vs6Sm7XLKXpixPxLmI3c=; b=JY/B9Ia3Hwuv98iBqooJxp4jaGNBG5RbWgvwUuFl6K/xkM0nq30C/WBUYqjycc1GK8b2J3vuN BhJjJD9uE57A+CSdMEkUIUK0yw/BkSPjGUoLII9VhHFArhcONNCX+X+ 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á Use the helper macro. No functional change intended... Signed-off-by: Nuno Sá --- drivers/mfd/adp5585.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/adp5585.c b/drivers/mfd/adp5585.c index f17b5f2474cac6a403556694066f438288264a49..fafe3ad93ea196e1eb8e79fecba58f36f12167eb 100644 --- a/drivers/mfd/adp5585.c +++ b/drivers/mfd/adp5585.c @@ -4,6 +4,7 @@ * * Copyright 2022 NXP * Copyright 2024 Ideas on Board Oy + * Copyright 2025 Analog Devices Inc. */ #include @@ -18,8 +19,10 @@ #include static const struct mfd_cell adp5585_devs[] = { - { .name = "adp5585-gpio", }, - { .name = "adp5585-pwm", }, + MFD_CELL_NAME("adp5585-keys"), + MFD_CELL_NAME("adp5585-gpio"), + MFD_CELL_NAME("adp5585-pwm"), + }; static const struct regmap_range adp5585_volatile_ranges[] = { From patchwork Thu Mar 13 14:19: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: 873653 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 17416268685; Thu, 13 Mar 2025 14:19:17 +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=1741875558; cv=none; b=nUHMVO09h4h6ZogxXvYLhJ2xIMwokZHo2PrL5zbxX7Al6FbJneeIGCGWyF4y2TafMJFTU3l/TDln/Sh6vIwTJ0zYRfFhzkgLbD6YIgKvibs3QQLXnBSSoAeOck+Ux9FwGP6qt7BES374GPJn/BamP+KeebR0iT/v1EdCk0mjlxI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875558; c=relaxed/simple; bh=ZuPpUZrWrIanIwjB5TcqWxXnwChpucCUCkIsIN8Afz4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dS7mWMoHOXrQPGTq3Ih24e3nLGoHWIdSymunq1Wgd2O+0OARMBf7q2EmCK667pQtwUSbq2ev74/OOIhbVEwNQ2stu8oDyFeMIxe8l31wSU7QzRmRZsntNvgGBcdCh6bOkc7hUcXFl5SVYKZVB4EdyuuuO9PONTqflc1LMGgJQnc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Tb956yzY; 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="Tb956yzY" Received: by smtp.kernel.org (Postfix) with ESMTPS id 92AC1C4CEFB; Thu, 13 Mar 2025 14:19:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875557; bh=ZuPpUZrWrIanIwjB5TcqWxXnwChpucCUCkIsIN8Afz4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Tb956yzYhKE96yA+MRPFe0aFg5tGxYgZnyKay7GU/dVlsDUpIwPrnzHb6tcUyh8kT 2RVIlKbHTtSe7KVD8uAy06a38yhmw/5zIEURNcklWU1Po9Po4rYq8Gk9k2hw7gb6aR 0DcwokjgkV0mj7mWVRQrUzDEuzlb2r30u2g2KzW0DX38NIZvOw7w/Hv+8/cjsErnvz 8eDBfKtcvtYquvNgQ+jljbUySNLcC/D4qW8EBhBOTB2QV6mHHkdBSbAEELJPW74QF0 Fs3OVIv+VfEOdlOzJhvXW0Oqxdrcxr6Pk/Nh5q+Ldd0QWf1d/uW2zlEWWmaXVn4cOB we81Z0X5/Cjog== 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 89AB2C35FF3; Thu, 13 Mar 2025 14:19:17 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:22 +0000 Subject: [PATCH 05/18] dt-bindings: mfd: adp5585: document adp5589 I/O expander Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-5-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875561; l=3546; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=rrvfmHEXd0tTkBviDQann7NZgieOZ479PPjxFhfnUAI=; b=0uqWM3h49M4V7Pzhax4lfh3//ckEIRqpyBwLyN1l8NQd6sY4WeVMEaInpstcHCyJ0LfiMnPiL Zx5S8OSzv/KCsS3i9uCFOkB7Gp8qdsJQgRbNO8SM+yxjgoLiOIWdEPO 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 | 48 +++++++++++++++------- .../devicetree/bindings/trivial-devices.yaml | 2 - 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml b/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml index e30e22f964f78519b2ec207e9415e4897db5c702..87256a37b5f4b6a019f581b164c276d8805d2e52 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 @@ -63,13 +70,26 @@ allOf: properties: gpio-reserved-ranges: false else: - properties: - gpio-reserved-ranges: - maxItems: 1 - items: + if: + properties: + compatible: + contains: + enum: + - adi,adp5585-00 + - adi,adp5585-02 + - adi,adp5585-03 + - adi,adp5585-04 + then: + properties: + gpio-reserved-ranges: + maxItems: 1 items: - - const: 5 - - const: 1 + items: + - const: 5 + - const: 1 + else: + properties: + gpio-reserved-ranges: false additionalProperties: false diff --git a/Documentation/devicetree/bindings/trivial-devices.yaml b/Documentation/devicetree/bindings/trivial-devices.yaml index fadbd3c041c8c39faedfe62874d4eba25a0bf30e..bdf0afb9301181b3f95fb7125302304834bdee94 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 Thu Mar 13 14:19: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: 873249 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 EBFE7267F7A; Thu, 13 Mar 2025 14:19:17 +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=1741875558; cv=none; b=uMkQzsF1rNd+dqDiu+oAXx/hNZ45G1kTX/ajnAzlRHX5FVk20Ijge+xFk1Enu2CHVJKNk7QGncGZeumPUYcLv+6+m5Qzm8RzvhmCQgZ1kkEsYw+HmA/3+DmN8aIYcWBvlas2GdTgc4ChxzO4/H+3HdAUYnmQDd/ouGUPnhfo6DA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875558; c=relaxed/simple; bh=o5yBWRYFffB+B6HFBigf6FuZSl3VOZCp/XCrSOcXnGQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NYmaW92J5krOOXVPoWKjjm2oNesooJfIcsKO0PL5nV+qWtMjGTVZSbz6U/lEk0q+cbnPRdtfDpMRex/PzOBHGSGIOx13Vmlivkad6NLpzMm/Ekv9N6yDGQxA35IyrwQXvXBmIDC1MgaY6ZLx1RRVQZbgKPbSHlIrjjhff0W/OPE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KAG1I6nl; 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="KAG1I6nl" Received: by smtp.kernel.org (Postfix) with ESMTPS id B1699C113D0; Thu, 13 Mar 2025 14:19:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875557; bh=o5yBWRYFffB+B6HFBigf6FuZSl3VOZCp/XCrSOcXnGQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=KAG1I6nlgX67/lfcIx3oExTNcGUqlww4vy4cF7ouro2IhaEqG0EoI4T2YUGn1CwUs hAXBxfO+1qkqPGneuS4Q+wE8TPO5TICK7iWYSOBIQ7KTpuYN4ppULtZ/sSq79431PY WwMHa1Get/Kcf4SHWXDZu/UV2YR2yRcTQ9murPvGCUIxzKbv7v7iVjzptumVrI+9rz eL/RGyZfGDd++Dz9JW+S0+hlRzrIZ0f748foi+Barhnf57FJciuc67OCLCYnDnWHnT MCBZSjzQdgCPIOOCAZdZU9jhjBdWKPdM3UeLOSviBKEGUojpklvnMEGLiZeO1uYcHZ S2OYuUbazjRqg== 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 A0B6EC282DE; Thu, 13 Mar 2025 14:19:17 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:23 +0000 Subject: [PATCH 06/18] mfd: adp5585: add support for adp5589 Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-6-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875561; l=13307; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=B0MInnU7VvqcOXSj1PG2OiRKYWLWNMbXF/wxzsCpKPY=; b=1EAgWpkBZ6yerxkQOym0NzHpIMtqto6bV3RutrtHguSHxYTDp17VNldK2wPhMynoubqfdID3X FLHfk2J2RPPCG55zU2AF9EXO64/HuizvL5RbB95jXeN4gn19W0iXbel 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 | 215 ++++++++++++++++++++++++++++++++++++++++++-- include/linux/mfd/adp5585.h | 57 +++++++++++- 2 files changed, 264 insertions(+), 8 deletions(-) diff --git a/drivers/mfd/adp5585.c b/drivers/mfd/adp5585.c index fafe3ad93ea196e1eb8e79fecba58f36f12167eb..2fedc1c7cd08a7b3a8c7188d3e7cdfdf3122a214 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 = &adp5585_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 = &adp5585_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 = &adp5585_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"); @@ -203,7 +392,19 @@ static const struct of_device_id adp5585_of_match[] = { .data = &adp5585_regmap_configs[ADP5585_REGMAP_00], }, { .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 Thu Mar 13 14:19:24 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: 873247 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 60BDB268C4B; Thu, 13 Mar 2025 14:19:17 +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=1741875558; cv=none; b=sYA9LwnV1Ns0SUfFneAGi6EB6IkBye5BV+MzPbbfgZAHsnIXoRVzNNVksawxrCSkPds2YzQI5nxHtTCyHM6Z9FQtfTTAUaqn/nGN1N3Zyo+tK17CAkV/1bum2eREQZ+uKL07HITl14oxRBhAq71KRCYzMr1Vl7B96yDNdyLPx0s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875558; c=relaxed/simple; bh=5JP+cDdGDswDwx7g92afORYwtD/xPpQe+hAqWjgN8JI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZjYdaNVC+vm5hUHZek1htPTRkz4ph2MiB1pekYImEwEXBOQSn2z/zb1wE2qaor0uCeoDyDPZTBFuykuGcAt4J42bpA+iR/d28g+7puHjj3+9PnR8koiICHSN7J4YGkJrnpdybW0eILQ9PYJZVKhh9qxeZGN5leZ1I3g4H354LLk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Tysgpgvg; 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="Tysgpgvg" Received: by smtp.kernel.org (Postfix) with ESMTPS id D2DD6C4CEF0; Thu, 13 Mar 2025 14:19:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875557; bh=5JP+cDdGDswDwx7g92afORYwtD/xPpQe+hAqWjgN8JI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Tysgpgvg8g1jbsgoJmUSYE6nxqkQ7qyIOVtTtT/R5qtHlTs2mdhRwnJzro7pmg5ky gyYqWpUxZGGlDYvGZ1L+aDVI76o0JOJfgK51a6LD2OPyK7yXTfmb0GVwoBtzK8UCs2 6m1oml/16ta1T1KfBKNU6F5IXTiLm2+VYDe+CkEOX1yrcadfVFZl8gzfq9oOFlOQJR yJZ6NKmN6W4VmOJjxRKicIFf4EFuIvONI47Yr5xqvEfjRlAOudlh6pW+DXMWCCOMhi psVDDIs96NQd+iVOGO8KwYpYZ8TKHkf3uUy4gbT0wFYGqeg9ZbevibOwGFFUHWC/Ud bv7T97IVBK6Gg== 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 CA7FBC282EC; Thu, 13 Mar 2025 14:19:17 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:24 +0000 Subject: [PATCH 07/18] gpio: adp5585: add support for the ad5589 expander Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-7-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875561; l=9246; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=En/L9MCOHXbURTimhYsnktNaqCUSWhDUSGL0YSjg2b4=; b=GLsjrr6HEqHGMIJ06AjYlbAdVNkx4dcE2FlN1hmWi7lCe+hKlo8Vw2jqtlKhWU0b1sI8izUTw wdkIRfzPGTsDQAbBksHAbOrB7W6PNk9/RVUBuJ7CEVmsUXlw+8dFoRT 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. Signed-off-by: Nuno Sá Acked-by: Linus Walleij --- drivers/gpio/gpio-adp5585.c | 120 ++++++++++++++++++++++++++++++++------------ 1 file changed, 88 insertions(+), 32 deletions(-) diff --git a/drivers/gpio/gpio-adp5585.c b/drivers/gpio/gpio-adp5585.c index 000d31f09671022e27b9087f9f01593520535b12..fded9ff35a59fc1a0ce173c58dbd7b6af176958f 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); @@ -89,16 +120,19 @@ static int adp5585_gpio_get_value(struct gpio_chip *chip, unsigned int off) static void 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); - regmap_update_bits(adp5585_gpio->regmap, ADP5585_GPO_DATA_OUT_A + bank, + 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; /* @@ -106,8 +140,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); @@ -117,22 +153,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); } @@ -173,6 +211,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; @@ -183,6 +222,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); @@ -197,7 +241,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; @@ -209,8 +253,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 Thu Mar 13 14:19:25 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: 873652 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 5E9FC268C4A; Thu, 13 Mar 2025 14:19:18 +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=1741875558; cv=none; b=mbbkB0ask/uF7Eb08OaXvOOEvkUmH3PNEegEH6yCAYz7UdQgQ7aNhYyKWxPyKfD9oEuzApiH3PEjGTODA6cPFxdOoMemIuSj8Wdv1+gcL5iDP70Mkl607Go6E9x8/8Hpkf6Q6sesgLnNEtHK/YoE2GK0ZGjVt+y8BmoGINXF0No= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875558; c=relaxed/simple; bh=B42mAyobrVzFGqDXmeLVCOlApD62miY7L/kyPIaBRrU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bB9b6gLxzvFv6dEeQLh7M5kXDz8xhT3dXtgEmgjqHkSEzdYdUG9hZtihqnUL+XUsHb6g3bI+SUpVWdlSrC90sj4baKZlPUlMarQF1VFPFqWqszWTT2OdZog+1xrFPjOVN+BM2TKB7neNNded34sBtsL/YcoEtsyiZzHEe6w0l3M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Tn9L5pf2; 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="Tn9L5pf2" Received: by smtp.kernel.org (Postfix) with ESMTPS id E6C7DC116C6; Thu, 13 Mar 2025 14:19:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875558; bh=B42mAyobrVzFGqDXmeLVCOlApD62miY7L/kyPIaBRrU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Tn9L5pf2ZVw0D2vomm7ZrwdhDbNFqHzEnFX1nbtwK0jGfsMw2V6ReeXO9OjnOiON8 jh2H8xZnhPq0DmWmqp4V2T9jQyDYbRyqw2dU4FDkcbCcZESHlVAAMOHWSV/cij4NXx 6BrY3QTsOi/GqYYk8tltR1xKn3CSy/KkpCGc2ppCKb3G2ncIINv8gOJFB/xXsTT3kx Dw2EuRtYAClgbut3/PBq33Q6/zON7t2uZTvw/gLsPCTaUTqW2YSV2JDebCCC3u53i6 dl/045EmVeUZ19xHrQpq6wwmT3IxI7vuBZMJXb4a4qN8FnJXIiGLu+3I+XfmEptIbC pUk23DIncovtg== 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 DE402C28B2E; Thu, 13 Mar 2025 14:19:17 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:25 +0000 Subject: [PATCH 08/18] pwm: adp5585: add support for adp5589 Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-8-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875561; l=5649; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=hDQwADPyhZkCjzlHyCqBfWfElr8WKeXEQSF0RoHBdlI=; b=Nd7LWJ9g/k5y/A7ktl2WQVKmHJG9HZizRfvBLYtyVU1Vq30DKIjkapKCXqywu8QUt0oadYIZE zUIZ9A3dUICBhSa1IT4Jf3XxYs50+CFBdS37Y7upPCLJP2iI/6yLuH9 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á Add support for the adp5589 I/O expander. From a PWM point of view it is pretty similar to adp5585. Main difference is the address of registers meaningful for configuring the PWM. Signed-off-by: Nuno Sá --- drivers/pwm/pwm-adp5585.c | 51 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/drivers/pwm/pwm-adp5585.c b/drivers/pwm/pwm-adp5585.c index c8821035b7c1412a55a642e6e8a46b66e693a5af..cc8ac8f9e5669b4ffca06d4117a29f030393f48f 100644 --- a/drivers/pwm/pwm-adp5585.c +++ b/drivers/pwm/pwm-adp5585.c @@ -32,21 +32,30 @@ #define ADP5585_PWM_MIN_PERIOD_NS (2ULL * NSEC_PER_SEC / ADP5585_PWM_OSC_FREQ_HZ) #define ADP5585_PWM_MAX_PERIOD_NS (2ULL * 0xffff * NSEC_PER_SEC / ADP5585_PWM_OSC_FREQ_HZ) +struct adp5585_pwm { + const struct adp5585_regs *regs; + struct regmap *regmap; +}; + static int pwm_adp5585_request(struct pwm_chip *chip, struct pwm_device *pwm) { - struct regmap *regmap = pwmchip_get_drvdata(chip); + struct adp5585_pwm *adp5585_pwm = pwmchip_get_drvdata(chip); + const struct adp5585_regs *regs = adp5585_pwm->regs; + struct regmap *regmap = adp5585_pwm->regmap; /* Configure the R3 pin as PWM output. */ - return regmap_update_bits(regmap, ADP5585_PIN_CONFIG_C, + return regmap_update_bits(regmap, regs->ext_cfg, ADP5585_R3_EXTEND_CFG_MASK, ADP5585_R3_EXTEND_CFG_PWM_OUT); } static void pwm_adp5585_free(struct pwm_chip *chip, struct pwm_device *pwm) { - struct regmap *regmap = pwmchip_get_drvdata(chip); + struct adp5585_pwm *adp5585_pwm = pwmchip_get_drvdata(chip); + const struct adp5585_regs *regs = adp5585_pwm->regs; + struct regmap *regmap = adp5585_pwm->regmap; - regmap_update_bits(regmap, ADP5585_PIN_CONFIG_C, + regmap_update_bits(regmap, regs->ext_cfg, ADP5585_R3_EXTEND_CFG_MASK, ADP5585_R3_EXTEND_CFG_GPIO4); } @@ -55,14 +64,16 @@ static int pwm_adp5585_apply(struct pwm_chip *chip, struct pwm_device *pwm, const struct pwm_state *state) { - struct regmap *regmap = pwmchip_get_drvdata(chip); + struct adp5585_pwm *adp5585_pwm = pwmchip_get_drvdata(chip); + const struct adp5585_regs *regs = adp5585_pwm->regs; + struct regmap *regmap = adp5585_pwm->regmap; u64 period, duty_cycle; u32 on, off; __le16 val; int ret; if (!state->enabled) { - regmap_clear_bits(regmap, ADP5585_PWM_CFG, ADP5585_PWM_EN); + regmap_clear_bits(regmap, regs->pwm_cfg, ADP5585_PWM_EN); return 0; } @@ -83,41 +94,43 @@ static int pwm_adp5585_apply(struct pwm_chip *chip, off = div_u64(period, NSEC_PER_SEC / ADP5585_PWM_OSC_FREQ_HZ) - on; val = cpu_to_le16(off); - ret = regmap_bulk_write(regmap, ADP5585_PWM_OFFT_LOW, &val, 2); + ret = regmap_bulk_write(regmap, regs->pwm_offt_low, &val, 2); if (ret) return ret; val = cpu_to_le16(on); - ret = regmap_bulk_write(regmap, ADP5585_PWM_ONT_LOW, &val, 2); + ret = regmap_bulk_write(regmap, regs->pwm_ont_low, &val, 2); if (ret) return ret; /* Enable PWM in continuous mode and no external AND'ing. */ - ret = regmap_update_bits(regmap, ADP5585_PWM_CFG, + ret = regmap_update_bits(regmap, regs->pwm_cfg, ADP5585_PWM_IN_AND | ADP5585_PWM_MODE | ADP5585_PWM_EN, ADP5585_PWM_EN); if (ret) return ret; - return regmap_set_bits(regmap, ADP5585_PWM_CFG, ADP5585_PWM_EN); + return regmap_set_bits(regmap, regs->pwm_cfg, ADP5585_PWM_EN); } static int pwm_adp5585_get_state(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state) { - struct regmap *regmap = pwmchip_get_drvdata(chip); + struct adp5585_pwm *adp5585_pwm = pwmchip_get_drvdata(chip); + const struct adp5585_regs *regs = adp5585_pwm->regs; + struct regmap *regmap = adp5585_pwm->regmap; unsigned int on, off; unsigned int val; __le16 on_off; int ret; - ret = regmap_bulk_read(regmap, ADP5585_PWM_OFFT_LOW, &on_off, 2); + ret = regmap_bulk_read(regmap, regs->pwm_offt_low, &on_off, 2); if (ret) return ret; off = le16_to_cpu(on_off); - ret = regmap_bulk_read(regmap, ADP5585_PWM_ONT_LOW, &on_off, 2); + ret = regmap_bulk_read(regmap, regs->pwm_ont_low, &on_off, 2); if (ret) return ret; on = le16_to_cpu(on_off); @@ -127,7 +140,7 @@ static int pwm_adp5585_get_state(struct pwm_chip *chip, state->polarity = PWM_POLARITY_NORMAL; - regmap_read(regmap, ADP5585_PWM_CFG, &val); + regmap_read(regmap, regs->pwm_cfg, &val); state->enabled = !!(val & ADP5585_PWM_EN); return 0; @@ -144,16 +157,21 @@ static int adp5585_pwm_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct adp5585_dev *adp5585 = dev_get_drvdata(dev->parent); + struct adp5585_pwm *adp5585_pwm; struct pwm_chip *chip; int ret; - chip = devm_pwmchip_alloc(dev, ADP5585_PWM_CHAN_NUM, 0); + chip = devm_pwmchip_alloc(dev, ADP5585_PWM_CHAN_NUM, + sizeof(*adp5585_pwm)); if (IS_ERR(chip)) return PTR_ERR(chip); + adp5585_pwm = pwmchip_get_drvdata(chip); + adp5585_pwm->regmap = adp5585->regmap; + adp5585_pwm->regs = adp5585->info->regs; + device_set_of_node_from_dev(dev, dev->parent); - pwmchip_set_drvdata(chip, adp5585->regmap); chip->ops = &adp5585_pwm_ops; ret = devm_pwmchip_add(dev, chip); @@ -165,6 +183,7 @@ static int adp5585_pwm_probe(struct platform_device *pdev) static const struct platform_device_id adp5585_pwm_id_table[] = { { "adp5585-pwm" }, + { "adp5589-pwm" }, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(platform, adp5585_pwm_id_table); From patchwork Thu Mar 13 14:19: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: 873248 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 2E60326869F; Thu, 13 Mar 2025 14:19:18 +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=1741875558; cv=none; b=Y0yhjJlz8Rts6gGwEV3HgYoevDrcjSxewk2wr1leVfBuDEVZ6l2EAAWgqoXtSpWka/OAQGGO5Pi7mva4tUMPwkd9d7sw5mARIK/4Oxk999gu0gIJ4z+IHFAULYjU5k51c8q/ZYuhP7h5UGO9LFnb1xdxXRylbIOXB/bA8ZAo41c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875558; c=relaxed/simple; bh=Fn7k3XRmgGeTcU5L6r0+n5XDkdk/fxr+UU17KnsKoac=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=RyRxycFaQpMMOTRMZBKftIwiou4dySXRxi+A25Yh1q5HRyO32A7kUQvGC37xfdn2qwfyT1EqXdiSuALZg8mKJI9/YnDhI62NRqbcF35i3y1plXrGZHmJHEVltcB6cyYlDw+aei288vWI9We5cO/zQLyxD5FFAwF6qIoGb4IxCYM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=S79RwY+W; 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="S79RwY+W" Received: by smtp.kernel.org (Postfix) with ESMTPS id 094E6C2BC87; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875558; bh=Fn7k3XRmgGeTcU5L6r0+n5XDkdk/fxr+UU17KnsKoac=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=S79RwY+WNYEbT+JJ6UKWq8MWOlLkMwMFBAt45C6gNCQErd5IKUydv0LYqgCmoQCvb VucJR+4K3Ae5Fe24L1TBMjeFc3Dp8X/b5GorJW032IpLmUXLErLJZBQ93ScRHzfXVo rMe188j6Z2QF+RwWmFBZbGqV2dFLiDHAc4hykjzoy1PbeMOkDFz68NJlN45+2HCpdp KivD1Oa1x6qoGnFunoI/liKGXNkOuQ0DkWMYSrnwoHHicbMpI9SbpfCVskYsuLJr3g mh9XUieFelrsO25wgd05jI8dqV/3DRWWEdY2AvGmTolS9AlPXGqyWgXD+zDSY7kEcZ 66hH50+zygkPg== 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 F2391C282EC; Thu, 13 Mar 2025 14:19:17 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:26 +0000 Subject: [PATCH 09/18] dt-bindings: mfd: adp5585: add properties for input events Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-9-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875561; l=7712; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=ypEFkxleuONgmcwAw/524X6k+fiuPuF+VdlS5uAV6c0=; b=jUMp/8OX8QJ/McPQHFEUltq4QahrfNA2SqAeHM3JrMSUQJEp1hciJ+gy0/BfYN1GAE3NxTQPY gbSdx0ZDpN3BYJ4RC+RP/jK+CmegX3alrDUPvu8BYtEa2WHe0DuHE/N 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á Add properties related to input events. These devices can act as keyboards and can support events either via a keymap Matrix or through GPIs. Note that the device needs to be an interrupt controller for GPIs based events. We specifically need a property specifying the pins used by the keymap matrix since these devices have no requirement for rows and columns to be contiguous without holes which is enforced by the standard input properties. Signed-off-by: Nuno Sá --- .../devicetree/bindings/mfd/adi,adp5585.yaml | 188 ++++++++++++++++++++- 1 file changed, 187 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml b/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml index 87256a37b5f4b6a019f581b164c276d8805d2e52..e976c9240df79afae1d0949e6ac91d477bfaceef 100644 --- a/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml +++ b/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml @@ -49,6 +49,85 @@ properties: "#pwm-cells": const: 3 + interrupt-controller: true + + '#interrupt-cells': + const: 2 + + adi,keypad-pins: + description: Specifies the pins used for the keypad matrix. + $ref: /schemas/types.yaml#/definitions/uint32-array + + adi,key-poll-ms: + description: Configure time between consecutive scan cycles. + enum: [10, 20, 30, 40] + default: 10 + + adi,unlock-keys: + description: + Specifies a maximum of 2 keys that can be used to unlock the keypad. + If this property is set, the keyboard will be locked and only unlocked + after these keys are pressed. The value 127 serves as a wildcard which + means any key can be used for unlocking. + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 1 + maxItems: 2 + items: + anyOf: + - minimum: 1 + maximum: 88 + - minimum: 97 + maximum: 115 + - const: 127 + + adi,unlock-trigger-sec: + description: + Defines the time in which the second unlock event must occur after the + first unlock event has occurred. + maximum: 7 + default: 0 + + adi,reset1-keys: + description: + Defines the trigger events (key presses) that can generate reset + conditions one the reset1 block. + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 1 + maxItems: 3 + + adi,reset2-keys: + description: + Defines the trigger events (key presses) that can generate reset + conditions one the reset2 block. + $ref: /schemas/types.yaml#/definitions/uint32-array + minItems: 1 + maxItems: 2 + + adi,reset1-active-high: + description: Sets the reset1 signal as active high. + type: boolean + + adi,reset2-active-high: + description: Sets the reset2 signal as active high. + type: boolean + + adi,rst-passtrough-enable: + description: Allows the RST pin to override (OR with) the reset1 signal. + type: boolean + + adi,reset-trigger-ms: + description: + Defines the length of time that the reset events must be active before a + reset signal is generated. All events must be active at the same time for + the same duration. + enum: [0, 1000, 1500, 2000, 2500, 3000, 3500, 4000] + default: 0 + + adi,reset-pulse-width-us: + description: Defines the pulse width of the reset signals. + enum: [500, 1000, 2000, 10000] + default: 500 + patternProperties: "-hog(-[0-9]+)?$": type: object @@ -56,11 +135,28 @@ patternProperties: required: - gpio-hog +dependencies: + linux,keymap: + - adi,keypad-pins + - interrupts + interrupt-controller: + - interrupts + adi,unlock-trigger-sec: + - adi,unlock-keys + adi,reset1-active-high: + - adi,reset1-keys + adi,rst-passtrough-enable: + - adi,reset1-keys + adi,reset2-active-high: + - adi,reset2-keys + required: - compatible - reg allOf: + - $ref: /schemas/input/matrix-keymap.yaml# + - $ref: /schemas/input/input.yaml# - if: properties: compatible: @@ -68,7 +164,29 @@ allOf: const: adi,adp5585-01 then: properties: + adi,unlock-keys: false + adi,unlock-trigger-sec: false gpio-reserved-ranges: false + adi,keypad-pins: + minItems: 2 + maxItems: 11 + items: + minimum: 0 + maximum: 10 + adi,reset1-keys: + items: + anyOf: + - minimum: 1 + maximum: 30 + - minimum: 37 + maximum: 47 + adi,reset2-keys: + items: + anyOf: + - minimum: 1 + maximum: 30 + - minimum: 37 + maximum: 47 else: if: properties: @@ -81,6 +199,25 @@ allOf: - adi,adp5585-04 then: properties: + adi,unlock-keys: false + adi,unlock-trigger-sec: false + adi,keypad-pins: + minItems: 2 + maxItems: 10 + items: + enum: [0, 1, 2, 3, 4, 6, 7, 8, 9, 10] + adi,reset1-keys: + items: + anyOf: + - minimum: 1 + maximum: 25 + - enum: [37, 38, 39, 40, 41, 43, 44, 45, 46, 47] + adi,reset2-keys: + items: + anyOf: + - minimum: 1 + maximum: 25 + - enum: [37, 38, 39, 40, 41, 43, 44, 45, 46, 47] gpio-reserved-ranges: maxItems: 1 items: @@ -90,11 +227,33 @@ allOf: else: properties: gpio-reserved-ranges: false + adi,keypad-pins: + minItems: 2 + maxItems: 19 + items: + minimum: 0 + maximum: 18 + adi,reset1-keys: + items: + anyOf: + - minimum: 1 + maximum: 88 + - minimum: 97 + maximum: 115 + adi,reset2-keys: + items: + anyOf: + - minimum: 1 + maximum: 88 + - minimum: 97 + maximum: 115 -additionalProperties: false +unevaluatedProperties: false examples: - | + #include + #include i2c { #address-cells = <1>; #size-cells = <0>; @@ -110,6 +269,33 @@ examples: gpio-reserved-ranges = <5 1>; #pwm-cells = <3>; + + interrupts = <16 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent = <&gpio>; + + adi,reset1-keys = <1 43>; + adi,reset2-keys = <2 3>; + adi,reset-trigger-ms = <2000>; + + /* + * col0, col1, col2 + * row0, row1, row2 + */ + adi,keypad-pins = <0 1 2 6 7 8>; + + linux,keymap = < + MATRIX_KEY(0x00, 0x00, KEY_1) + MATRIX_KEY(0x00, 0x01, KEY_2) + MATRIX_KEY(0x00, 0x02, KEY_3) + + MATRIX_KEY(0x01, 0x00, KEY_A) + MATRIX_KEY(0x01, 0x01, KEY_B) + MATRIX_KEY(0x01, 0x02, KEY_C) + + MATRIX_KEY(0x02, 0x00, BTN_1) + MATRIX_KEY(0x02, 0x01, BTN_2) + MATRIX_KEY(0x02, 0x02, BTN_3) + >; }; }; From patchwork Thu Mar 13 14:19:27 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: 873647 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 9D1662690ED; Thu, 13 Mar 2025 14:19:18 +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=1741875559; cv=none; b=YkYI3Pg4XJUCVsWSFMbzBqz9PO29jxfAvm+xAv/YgV5fPEaQOM0uQnWCTSKdjNwcM9FjcDv0LYzI8W8QNYRUnkiPZtNKRoP4TpIsPipw81fgPJ2r9vf04oztOxVhXj/4FZfuXmve3psK/7Nrn6JYBDN3chaEsB4udh+dEI8sESU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875559; c=relaxed/simple; bh=ODQyyTC3KtS5yYHkwiErTaUxQgX/DDQHl9yIHI7uJ6g=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=B7C6U7Wo9R4wKJsPhKTT/DiAL9tYtdlerkhKz/xMAyoSq9hwjDbrPSRj+jmZtcA5qwFnYO+IgSoPDb4aDtRWbsX7e5i7zm309VG+ExyBKp51acmB/vfwex5LfrQg6pjku9w2/ddnRir3fPgxCV2FMpxabg8zn4c2QuPBDpDsgN4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dYQXJMzK; 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="dYQXJMzK" Received: by smtp.kernel.org (Postfix) with ESMTPS id 1F7F3C4CEEE; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875558; bh=ODQyyTC3KtS5yYHkwiErTaUxQgX/DDQHl9yIHI7uJ6g=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=dYQXJMzKfFHPQisstOgeEpxjfb9R605tSkANbhyCq98zt0bWAFiqboydZ7S6u0miU eY3ZkFUM37wIYLGZfaF1rjaK913SxFXjY5hRlCf6yARwWrUq6TXMUW36Fculpgq2Ub Nsfvi677G+TrdkjJxmoFHXJYOMjxrNOZiMTroJLwIL5e7RuTQ/vN9WEYxC3Lgh/MzF 2ZVNJCL/Uqg7Se4nc+u8xWj6DS9Hw3omSMnG6QnUATfb74E0NojaWOh9IswcIhIZj2 dneTZD75tx4tD/EpakdCyf0/osIoQ4JGClzKdgZrKDzY0gQ7Hw8ULordOjCodwkLxg uc4YpyTGM1uVA== 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 13AE2C28B2E; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:27 +0000 Subject: [PATCH 10/18] mfd: adp5585: add support for key events Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-10-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875561; l=27152; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=u38RbMm5hL9EeT9hoC0FGy7iiATu4lyLXqcDrt0lYOs=; b=phgmFxhyZs2Wo04FXLEX4Xv/Bqt+bJmmrV+ZWrGBZLnVZCb+KeP3FJMmiqqXml08195tru4j0 k/AZOBeBYvKB//mshReN+9nChMxbWa1Ykg5By3K7oZE6XAXEA0IXiVt 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 | 550 +++++++++++++++++++++++++++++++++++++++++++- include/linux/mfd/adp5585.h | 96 ++++++++ 2 files changed, 641 insertions(+), 5 deletions(-) diff --git a/drivers/mfd/adp5585.c b/drivers/mfd/adp5585.c index 2fedc1c7cd08a7b3a8c7188d3e7cdfdf3122a214..a96de4e6a3a12e2c91528835c2061795e6ff3ed0 100644 --- a/drivers/mfd/adp5585.c +++ b/drivers/mfd/adp5585.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -205,11 +206,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 +228,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 +251,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 +260,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 +276,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 +288,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 +297,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 +311,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 +325,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 +705,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 +845,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 +863,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 +882,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 +900,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 Thu Mar 13 14:19: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: 873651 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 E5AA7268C4A; Thu, 13 Mar 2025 14:19:18 +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=1741875559; cv=none; b=GYUxc8rLOs5SZ5uKLxAqNflU51CupmUCz3KrAHg9iI/yiAJOIgZhbaGoGAOLjaJKNVJM7bQMr+T3CsZVyk4z7wH8h8aYGDDVN7R6dHvQbMq0+ZzNaAPn6uJimzCF3supEmmlqQdQd4UM1QZcnSltOdiv/iBXw9bOAebAgf9eCqA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875559; c=relaxed/simple; bh=HEAWSjMeUzmTyL+OFTVxnVs/A4wI2T7AEfQ4ou+0IhU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=j+hHut3J2NpJoezPBWSRM39SPjM93dqkiaw1eehQ7T1Chsm3+15a1aP2EiXv92wMuto/Pn3D1YduSD5P57E6NlGEbc97oJtwtrGJUgqYv3PoucFYDRhqvvbgieIrdlm3Bkl8hjDHYoNCQwPmdVt3WOuffsxiPfmJSvF+AVU+sl0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XS0IlNwH; 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="XS0IlNwH" Received: by smtp.kernel.org (Postfix) with ESMTPS id 2E83EC2BCB5; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875558; bh=HEAWSjMeUzmTyL+OFTVxnVs/A4wI2T7AEfQ4ou+0IhU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=XS0IlNwHtBWwZ3wGIKuZx5wIFI7Jbh7DXV62Uv0++BMAdoQWNwam9YXHGVjg/quip X/AHZnlj6eJMCYx83h+g1EjfipUOyTEbjtfmN0M9pKa6CH4ARbyxRVy9+3ySSxaQgq ACMdLODKUe79KxcNhVdUyN5FnMsk1J1wdzEuJVkkwXElZb2lWykWbKjteGjXC+J4IX XCZtvdkszc51iJra4ZkTFFLD9TGt4Htgsg9Igol9g8qF7LsZp/ibxkuzOowDdtg/vk fxXheFRkSKnQ8Z8xFaRSU2TPuvuM61oOJKccUSOk9d9VlhwXRM1qulOUlYLyAlsqc5 3jPUA99CiJOHA== 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 24EB5C282EC; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:28 +0000 Subject: [PATCH 11/18] gpio: adp5585: support gpi events Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-11-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875561; l=8240; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=5L3mKC5ksfSHBHoQXthkKPYdBIjhSE+HLAOYPQ/rbnI=; b=EoxlMFWo88cbjalZ0Jo7/kllIBcRA8V2GU967PiK5f0TbCpab/HT6+5IFlvB+RK08RsZgLxRn JI25gtyddNSB3rr48+OC5HAMhIMRwcj0pF1QNveJjmHLmRPjV1hJMdg 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á Add support for adding GPIs to the event FIFO. This is done by adding irq_chip support. Like this, one can use the input gpio_keys driver as a "frontend" device and input handler. As part of this change, we now implement .init_valid_mask() as we can't blindly consume all available pins as GPIOs (example: some pins can be used for forming a keymap matrix). Signed-off-by: Nuno Sá --- drivers/gpio/Kconfig | 1 + drivers/gpio/gpio-adp5585.c | 178 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 98b4d1633b258b93d05ba66d53f647e7ec6ac364..e8dc5cb9df0f62b111810d90ae67ce68b382d434 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1238,6 +1238,7 @@ config GPIO_ADP5520 config GPIO_ADP5585 tristate "GPIO Support for ADP5585" depends on MFD_ADP5585 + select GPIOLIB_IRQCHIP help This option enables support for the GPIO function found in the Analog Devices ADP5585. diff --git a/drivers/gpio/gpio-adp5585.c b/drivers/gpio/gpio-adp5585.c index fded9ff35a59fc1a0ce173c58dbd7b6af176958f..cfd0aab1f7414f76287714eda44184c615491194 100644 --- a/drivers/gpio/gpio-adp5585.c +++ b/drivers/gpio/gpio-adp5585.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,11 @@ struct adp5585_gpio_dev { const struct adp5585_gpio_chip *info; struct regmap *regmap; const struct adp5585_regs *regs; + unsigned long irq_mask; + unsigned long irq_en; + unsigned long irq_active_high; + /* used for irqchip bus locking */ + struct mutex bus_lock; }; static int adp5585_gpio_bank(unsigned int off) @@ -208,12 +214,155 @@ static int adp5585_gpio_set_config(struct gpio_chip *chip, unsigned int off, }; } +static int adp5585_gpio_init_valid_mask(struct gpio_chip *chip, + unsigned long *valid_mask, + unsigned int ngpios) +{ + struct device *dev = chip->parent; + struct adp5585_dev *adp5585 = dev_get_drvdata(dev->parent); + + bitmap_complement(valid_mask, adp5585->keypad, ngpios); + /* + * the keypad won't have (nor can't) have any special pin enabled which + * means bitmap_complement() will set them to 1. Make sure we clear them. + */ + if (adp5585->has_pwm) + __clear_bit(ADP5585_ROW3, valid_mask); + if (adp5585->nkeys_reset1) + __clear_bit(ADP5585_ROW4, valid_mask); + if (adp5585->nkeys_reset2) + __clear_bit(adp5585->info->max_rows + ADP5585_COL4, valid_mask); + if (!adp5585->info->has_row5) + __clear_bit(ADP5585_ROW5, valid_mask); + + return 0; +} + +static void adp5585_gpio_key_event(struct device *dev, unsigned int off, + bool key_press) +{ + struct adp5585_gpio_dev *adp5585_gpio = dev_get_drvdata(dev); + bool active_high = test_bit(off, &adp5585_gpio->irq_active_high); + unsigned int irq, irq_type; + struct irq_data *irqd; + + irq = irq_find_mapping(adp5585_gpio->gpio_chip.irq.domain, off); + if (!irq) + return; + + irqd = irq_get_irq_data(irq); + if (!irqd) { + dev_err(dev, "Could not get irq(%u) data\n", irq); + return; + } + + dev_dbg_ratelimited(dev, "gpio-keys event(%u) press=%u, a_high=%u\n", + off, key_press, active_high); + + if (!active_high) + key_press = !key_press; + + irq_type = irqd_get_trigger_type(irqd); + + if ((irq_type & IRQ_TYPE_EDGE_RISING && key_press) || + (irq_type & IRQ_TYPE_EDGE_FALLING && !key_press)) + handle_nested_irq(irq); +} + +static void adp5585_irq_bus_lock(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(gc); + + mutex_lock(&adp5585_gpio->bus_lock); +} + +static void adp5585_irq_bus_sync_unlock(struct irq_data *d) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(d); + struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip); + const struct adp5585_regs *regs = adp5585_gpio->regs; + irq_hw_number_t hwirq = irqd_to_hwirq(d); + bool active_high = test_bit(hwirq, &adp5585_gpio->irq_active_high); + bool enabled = test_bit(hwirq, &adp5585_gpio->irq_en); + bool masked = test_bit(hwirq, &adp5585_gpio->irq_mask); + unsigned int bank = adp5585_gpio->info->bank(hwirq); + unsigned int bit = adp5585_gpio->info->bit(hwirq); + + if (masked && !enabled) + goto out_unlock; + if (!masked && enabled) + goto out_unlock; + + regmap_update_bits(adp5585_gpio->regmap, regs->gpi_int_lvl_a + bank, bit, + active_high ? bit : 0); + regmap_update_bits(adp5585_gpio->regmap, regs->gpi_ev_a + bank, bit, + masked ? 0 : bit); + assign_bit(hwirq, &adp5585_gpio->irq_en, !masked); + +out_unlock: + mutex_unlock(&adp5585_gpio->bus_lock); +} + +static void adp5585_irq_mask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(gc); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + __set_bit(hwirq, &adp5585_gpio->irq_mask); + gpiochip_disable_irq(gc, hwirq); +} + +static void adp5585_irq_unmask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(gc); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + gpiochip_enable_irq(gc, hwirq); + __clear_bit(hwirq, &adp5585_gpio->irq_mask); +} + +static int adp5585_irq_set_type(struct irq_data *d, unsigned int type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(gc); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + + if (!(type & IRQ_TYPE_EDGE_BOTH)) + return -EINVAL; + + assign_bit(hwirq, &adp5585_gpio->irq_active_high, + type == IRQ_TYPE_EDGE_RISING); + + irq_set_handler_locked(d, handle_edge_irq); + return 0; +} + +static const struct irq_chip adp5585_irq_chip = { + .name = "adp5585", + .irq_mask = adp5585_irq_mask, + .irq_unmask = adp5585_irq_unmask, + .irq_bus_lock = adp5585_irq_bus_lock, + .irq_bus_sync_unlock = adp5585_irq_bus_sync_unlock, + .irq_set_type = adp5585_irq_set_type, + .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + +static void adp5585_gpio_ev_handle_clean(void *adp5585) +{ + adp5585_gpio_ev_handle_set(adp5585, NULL, NULL); +} + 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_irq_chip *girq; struct gpio_chip *gc; int ret; @@ -238,6 +387,7 @@ static int adp5585_gpio_probe(struct platform_device *pdev) gc->get = adp5585_gpio_get_value; gc->set = adp5585_gpio_set_value; gc->set_config = adp5585_gpio_set_config; + gc->init_valid_mask = adp5585_gpio_init_valid_mask; gc->can_sleep = true; gc->base = -1; @@ -245,6 +395,34 @@ static int adp5585_gpio_probe(struct platform_device *pdev) gc->label = pdev->name; gc->owner = THIS_MODULE; + if (device_property_present(dev->parent, "interrupt-controller")) { + if (!adp5585->irq) + return dev_err_probe(dev, -EINVAL, + "Unable to serve as interrupt controller without IRQ\n"); + + girq = &adp5585_gpio->gpio_chip.irq; + gpio_irq_chip_set_chip(girq, &adp5585_irq_chip); + girq->handler = handle_bad_irq; + girq->threaded = true; + + platform_set_drvdata(pdev, adp5585_gpio); + adp5585_gpio_ev_handle_set(adp5585, adp5585_gpio_key_event, + dev); + + ret = devm_add_action_or_reset(dev, + adp5585_gpio_ev_handle_clean, + adp5585); + if (ret) + return ret; + } + + /* everything masked by default */ + adp5585_gpio->irq_mask = ~0UL; + + ret = devm_mutex_init(dev, &adp5585_gpio->bus_lock); + if (ret) + return ret; + ret = devm_gpiochip_add_data(dev, &adp5585_gpio->gpio_chip, adp5585_gpio); if (ret) From patchwork Thu Mar 13 14:19:29 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: 873246 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 02BE7268C7F; Thu, 13 Mar 2025 14:19:18 +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=1741875559; cv=none; b=RNXF5IM52kn0ggLxaGJ9J0CR5Wp2HLqpmFo8Mbj7h5Zm5WNQSh6hKpp4+FjWrOzfPqixPfOJBPUD32+ZlNtaKhRouAvMbM6nV85dZ6PK+lNwoSvYEPEcrdRUYCRv4yj5PtOsTDoIB8P00pnFBalJ7sDbsFvZ0Ncx0+ztmjU6mj8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875559; c=relaxed/simple; bh=7tls/dbZLtpEqzrMx1gGjWfMhZOgychxmGds7O6hznY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Sd9w2iJGPhdhOyfTnjJSXZB3iF2eT6c3/tLK7QKXorl3YG894yIRz5YpiHKOvqQ32n4ijeeBw9FbQzGVCwtmm7UphfeQkCui15udXnkKA7J+yfURW6ZAVY2OUy7hzr3noKXzINzNZObgG4lt0Iv+ladDb7E2mxsqPO8vtc9IQOg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aAlsL51Q; 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="aAlsL51Q" Received: by smtp.kernel.org (Postfix) with ESMTPS id 3F728C4AF54; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875558; bh=7tls/dbZLtpEqzrMx1gGjWfMhZOgychxmGds7O6hznY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=aAlsL51QLzqn7d2ryzrUNcR4fWz1KlhSDksiSyqCGtWEPolsv7Pp66tb+fsH4LkkX tCevhSiGZvljWdgmXsLXuEpdzMvCrD9LZdk+XLrbBd+621/mOmO+JpWNrah+OzbkvI fmMhih5UDBQFWSgyIgccPVDZkodrKVU43K4SYad92NUQv1n8dPLbi4aS4z+AZkY7bt nipfNuNeZuZD8PRTVIkn4RGxi1ZUrYFwgOyjQQ72P+SU791A6oKssATOUbbr2EB3yf Z9JEOkbBOblfXmGusY0Wn1H6edtlocRy6BxQOmkGCYLf8MnBIc0VKmbKhN4dAICfag fOO7f5RLmE6lg== 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 34A9AC282DE; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:29 +0000 Subject: [PATCH 12/18] Input: adp5585: Add Analog Devices ADP5585/89 support Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-12-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875561; l=9142; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=F4e8yqUhSMjQO6ishzh/MCwUFayQhIqzfoE+Wv1l4n4=; b=I4UwMEVGLiteHGMCq1ySGA3ukZxME7fv63p79XouLVkuzjJxcvx1+c0Ko9UT0N63QpwkiORrU qZMfQ4Pxw7nC1BcrJfSjFXqqrRbcPL+FULpqpHo6tNBaMsM1ehK89zB 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 74964ea4e18794884db68b7a741426d2892f4274..e4afef16ae832a08301dbc81866dfc3a70b06910 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -548,6 +548,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 Thu Mar 13 14:19: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: 873245 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 2D433268FCC; Thu, 13 Mar 2025 14:19: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=1741875559; cv=none; b=nlRCzWOlFd2FO97S6u0vsIseqBzueD5u932mQEQL8XdehdTET5BaIxY2GnI90bpjC04A3RBAs7HIZChmhyEdddZUtFyAW7XsbmwdYyBrXckCTd88bX5+nh6sJG0glaZ/dNFxDwct/x75syu2FB9kbEG8195BlDPiWTPyk9TZkVw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875559; c=relaxed/simple; bh=nYb1hZaNYPmpQfxivEWflMQA8YVvTq+okB1MV7q1zUc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WFdRWBY7WUlDB4R5u+RiBkLwMCcSMscMhS1/AkK6OHzo5d+vNAkzMSkjBG/6utB9APWE8CTYYsNkKYTnxI5LKdPt9VBbKl3XaxcitXnwOLUsFXtAsUwILp7XJ69CqYyQk2hBIuuv9eLkI/8V3MW+KEMBB95CEAwkX+ZJHt7iWyY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MwiGdTXM; 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="MwiGdTXM" Received: by smtp.kernel.org (Postfix) with ESMTPS id 54AE8C4CEFA; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875558; bh=nYb1hZaNYPmpQfxivEWflMQA8YVvTq+okB1MV7q1zUc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=MwiGdTXMF5fsSBeppjzTdt2v09gBBC3ljrN+VvySxaraRnUxvkVX0usYRsDDIJm/o S9P40d1umsZwZvErQhkXNKrCUEvkNxeVj8WPtzHGVXtz0RxxUCj0/hNJP7/i9cmWTh +kMDoc0FVFCAhmnuuaVQOLxHIIWfsqftE8tiKH9oNmdsdwwhShONj/Zoa11z1uvpc7 buHJmQl6Esg/W1k8IZbCSqsoWr8U2PF8Rx9vVlJAMEF749iF9qXkdyh4xAUQJXntWM aaRifLfja2V3UaExaAZZvzJ9zSuqm+tEia+9yvuwbe+B+3KKLCvhB80ZQzsjoXdrn4 qQtTXj+8yiOtQ== 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 4784FC35FF3; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:30 +0000 Subject: [PATCH 13/18] Input: adp5589: remove the driver Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-13-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875561; l=33956; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=hRfONCC9CxGVto+jSjVPcjCOBG1ldqTuTwcfvMTylPk=; b=XMZ4sdZjPm4bsHsuQS37XxZBL1x+kcyOhmMANG3shYmo6Jn3RgQ748O1Z2d32x2bKWyiJ3Kit MkeIlryCo6BA4AtQ8JVXPN6NMNqNTglWSdsao0jnW2ZlhZJK9suKc9G 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 support is based on legacy platform data and there's no upstream pataform using this device. Moreover, recently, with commit 480a8ad683d7 ("mfd: adp5585: Add Analog Devices ADP5585 core support") we overlapped support for the adp5585 device (gpiochip part of it) but since it actually makes sense for the device to be supported under MFD, we can complement it and add the keymap support for it (properly based on FW properties). And that is what commit 04840c5363a6 ("Input: adp5585: Add Analog Devices ADP5585/89 support") is doing. Signed-off-by: Nuno Sá --- drivers/input/keyboard/Kconfig | 10 - drivers/input/keyboard/Makefile | 1 - drivers/input/keyboard/adp5589-keys.c | 1066 --------------------------------- 3 files changed, 1077 deletions(-) diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 322da0957067db77c7f66ab26a181d39c2c1d513..76d3397961fa006de4d5979e134b8c6e7dd52c73 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -61,16 +61,6 @@ config KEYBOARD_ADP5588 To compile this driver as a module, choose M here: the module will be called adp5588-keys. -config KEYBOARD_ADP5589 - tristate "ADP5585/ADP5589 I2C QWERTY Keypad and IO Expander" - depends on I2C - help - Say Y here if you want to use a ADP5585/ADP5589 attached to your - system I2C bus. - - To compile this driver as a module, choose M here: the - module will be called adp5589-keys. - config KEYBOARD_AMIGA tristate "Amiga keyboard" depends on AMIGA diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index f00ec003a59aa28577ae164c0539cc5aff9579fc..8bc20ab2b103b0b75c446e4aa919dad01aa5f405 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -9,7 +9,6 @@ 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 obj-$(CONFIG_KEYBOARD_APPLESPI) += applespi.o obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c deleted file mode 100644 index 81d0876ee358ef4b521f3f936dc2ab108bb4cda3..0000000000000000000000000000000000000000 --- a/drivers/input/keyboard/adp5589-keys.c +++ /dev/null @@ -1,1066 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Description: keypad driver for ADP5589, ADP5585 - * I2C QWERTY Keypad and IO Expander - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * Copyright (C) 2010-2011 Analog Devices Inc. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* ADP5589/ADP5585 Common Registers */ -#define ADP5589_5_ID 0x00 -#define ADP5589_5_INT_STATUS 0x01 -#define ADP5589_5_STATUS 0x02 -#define ADP5589_5_FIFO_1 0x03 -#define ADP5589_5_FIFO_2 0x04 -#define ADP5589_5_FIFO_3 0x05 -#define ADP5589_5_FIFO_4 0x06 -#define ADP5589_5_FIFO_5 0x07 -#define ADP5589_5_FIFO_6 0x08 -#define ADP5589_5_FIFO_7 0x09 -#define ADP5589_5_FIFO_8 0x0A -#define ADP5589_5_FIFO_9 0x0B -#define ADP5589_5_FIFO_10 0x0C -#define ADP5589_5_FIFO_11 0x0D -#define ADP5589_5_FIFO_12 0x0E -#define ADP5589_5_FIFO_13 0x0F -#define ADP5589_5_FIFO_14 0x10 -#define ADP5589_5_FIFO_15 0x11 -#define ADP5589_5_FIFO_16 0x12 -#define ADP5589_5_GPI_INT_STAT_A 0x13 -#define ADP5589_5_GPI_INT_STAT_B 0x14 - -/* ADP5589 Registers */ -#define ADP5589_GPI_INT_STAT_C 0x15 -#define ADP5589_GPI_STATUS_A 0x16 -#define ADP5589_GPI_STATUS_B 0x17 -#define ADP5589_GPI_STATUS_C 0x18 -#define ADP5589_RPULL_CONFIG_A 0x19 -#define ADP5589_RPULL_CONFIG_B 0x1A -#define ADP5589_RPULL_CONFIG_C 0x1B -#define ADP5589_RPULL_CONFIG_D 0x1C -#define ADP5589_RPULL_CONFIG_E 0x1D -#define ADP5589_GPI_INT_LEVEL_A 0x1E -#define ADP5589_GPI_INT_LEVEL_B 0x1F -#define ADP5589_GPI_INT_LEVEL_C 0x20 -#define ADP5589_GPI_EVENT_EN_A 0x21 -#define ADP5589_GPI_EVENT_EN_B 0x22 -#define ADP5589_GPI_EVENT_EN_C 0x23 -#define ADP5589_GPI_INTERRUPT_EN_A 0x24 -#define ADP5589_GPI_INTERRUPT_EN_B 0x25 -#define ADP5589_GPI_INTERRUPT_EN_C 0x26 -#define ADP5589_DEBOUNCE_DIS_A 0x27 -#define ADP5589_DEBOUNCE_DIS_B 0x28 -#define ADP5589_DEBOUNCE_DIS_C 0x29 -#define ADP5589_GPO_DATA_OUT_A 0x2A -#define ADP5589_GPO_DATA_OUT_B 0x2B -#define ADP5589_GPO_DATA_OUT_C 0x2C -#define ADP5589_GPO_OUT_MODE_A 0x2D -#define ADP5589_GPO_OUT_MODE_B 0x2E -#define ADP5589_GPO_OUT_MODE_C 0x2F -#define ADP5589_GPIO_DIRECTION_A 0x30 -#define ADP5589_GPIO_DIRECTION_B 0x31 -#define ADP5589_GPIO_DIRECTION_C 0x32 -#define ADP5589_UNLOCK1 0x33 -#define ADP5589_UNLOCK2 0x34 -#define ADP5589_EXT_LOCK_EVENT 0x35 -#define ADP5589_UNLOCK_TIMERS 0x36 -#define ADP5589_LOCK_CFG 0x37 -#define ADP5589_RESET1_EVENT_A 0x38 -#define ADP5589_RESET1_EVENT_B 0x39 -#define ADP5589_RESET1_EVENT_C 0x3A -#define ADP5589_RESET2_EVENT_A 0x3B -#define ADP5589_RESET2_EVENT_B 0x3C -#define ADP5589_RESET_CFG 0x3D -#define ADP5589_PWM_OFFT_LOW 0x3E -#define ADP5589_PWM_OFFT_HIGH 0x3F -#define ADP5589_PWM_ONT_LOW 0x40 -#define ADP5589_PWM_ONT_HIGH 0x41 -#define ADP5589_PWM_CFG 0x42 -#define ADP5589_CLOCK_DIV_CFG 0x43 -#define ADP5589_LOGIC_1_CFG 0x44 -#define ADP5589_LOGIC_2_CFG 0x45 -#define ADP5589_LOGIC_FF_CFG 0x46 -#define ADP5589_LOGIC_INT_EVENT_EN 0x47 -#define ADP5589_POLL_PTIME_CFG 0x48 -#define ADP5589_PIN_CONFIG_A 0x49 -#define ADP5589_PIN_CONFIG_B 0x4A -#define ADP5589_PIN_CONFIG_C 0x4B -#define ADP5589_PIN_CONFIG_D 0x4C -#define ADP5589_GENERAL_CFG 0x4D -#define ADP5589_INT_EN 0x4E - -/* ADP5585 Registers */ -#define ADP5585_GPI_STATUS_A 0x15 -#define ADP5585_GPI_STATUS_B 0x16 -#define ADP5585_RPULL_CONFIG_A 0x17 -#define ADP5585_RPULL_CONFIG_B 0x18 -#define ADP5585_RPULL_CONFIG_C 0x19 -#define ADP5585_RPULL_CONFIG_D 0x1A -#define ADP5585_GPI_INT_LEVEL_A 0x1B -#define ADP5585_GPI_INT_LEVEL_B 0x1C -#define ADP5585_GPI_EVENT_EN_A 0x1D -#define ADP5585_GPI_EVENT_EN_B 0x1E -#define ADP5585_GPI_INTERRUPT_EN_A 0x1F -#define ADP5585_GPI_INTERRUPT_EN_B 0x20 -#define ADP5585_DEBOUNCE_DIS_A 0x21 -#define ADP5585_DEBOUNCE_DIS_B 0x22 -#define ADP5585_GPO_DATA_OUT_A 0x23 -#define ADP5585_GPO_DATA_OUT_B 0x24 -#define ADP5585_GPO_OUT_MODE_A 0x25 -#define ADP5585_GPO_OUT_MODE_B 0x26 -#define ADP5585_GPIO_DIRECTION_A 0x27 -#define ADP5585_GPIO_DIRECTION_B 0x28 -#define ADP5585_RESET1_EVENT_A 0x29 -#define ADP5585_RESET1_EVENT_B 0x2A -#define ADP5585_RESET1_EVENT_C 0x2B -#define ADP5585_RESET2_EVENT_A 0x2C -#define ADP5585_RESET2_EVENT_B 0x2D -#define ADP5585_RESET_CFG 0x2E -#define ADP5585_PWM_OFFT_LOW 0x2F -#define ADP5585_PWM_OFFT_HIGH 0x30 -#define ADP5585_PWM_ONT_LOW 0x31 -#define ADP5585_PWM_ONT_HIGH 0x32 -#define ADP5585_PWM_CFG 0x33 -#define ADP5585_LOGIC_CFG 0x34 -#define ADP5585_LOGIC_FF_CFG 0x35 -#define ADP5585_LOGIC_INT_EVENT_EN 0x36 -#define ADP5585_POLL_PTIME_CFG 0x37 -#define ADP5585_PIN_CONFIG_A 0x38 -#define ADP5585_PIN_CONFIG_B 0x39 -#define ADP5585_PIN_CONFIG_D 0x3A -#define ADP5585_GENERAL_CFG 0x3B -#define ADP5585_INT_EN 0x3C - -/* ID Register */ -#define ADP5589_5_DEVICE_ID_MASK 0xF -#define ADP5589_5_MAN_ID_MASK 0xF -#define ADP5589_5_MAN_ID_SHIFT 4 -#define ADP5589_5_MAN_ID 0x02 - -/* GENERAL_CFG Register */ -#define OSC_EN BIT(7) -#define CORE_CLK(x) (((x) & 0x3) << 5) -#define LCK_TRK_LOGIC BIT(4) /* ADP5589 only */ -#define LCK_TRK_GPI BIT(3) /* ADP5589 only */ -#define INT_CFG BIT(1) -#define RST_CFG BIT(0) - -/* INT_EN Register */ -#define LOGIC2_IEN BIT(5) /* ADP5589 only */ -#define LOGIC1_IEN BIT(4) -#define LOCK_IEN BIT(3) /* ADP5589 only */ -#define OVRFLOW_IEN BIT(2) -#define GPI_IEN BIT(1) -#define EVENT_IEN BIT(0) - -/* Interrupt Status Register */ -#define LOGIC2_INT BIT(5) /* ADP5589 only */ -#define LOGIC1_INT BIT(4) -#define LOCK_INT BIT(3) /* ADP5589 only */ -#define OVRFLOW_INT BIT(2) -#define GPI_INT BIT(1) -#define EVENT_INT BIT(0) - -/* STATUS Register */ -#define LOGIC2_STAT BIT(7) /* ADP5589 only */ -#define LOGIC1_STAT BIT(6) -#define LOCK_STAT BIT(5) /* ADP5589 only */ -#define KEC 0x1F - -/* PIN_CONFIG_D Register */ -#define C4_EXTEND_CFG BIT(6) /* RESET2 */ -#define R4_EXTEND_CFG BIT(5) /* RESET1 */ - -/* LOCK_CFG */ -#define LOCK_EN BIT(0) - -#define PTIME_MASK 0x3 -#define LTIME_MASK 0x3 /* ADP5589 only */ - -/* Key Event Register xy */ -#define KEY_EV_PRESSED BIT(7) -#define KEY_EV_MASK 0x7F - -#define KEYP_MAX_EVENT 16 -#define ADP5589_MAXGPIO 19 -#define ADP5585_MAXGPIO 11 /* 10 on the ADP5585-01, 11 on ADP5585-02 */ - -enum { - ADP5589, - ADP5585_01, - ADP5585_02 -}; - -struct adp_constants { - u8 maxgpio; - u8 keymapsize; - u8 gpi_pin_row_base; - u8 gpi_pin_row_end; - u8 gpi_pin_col_base; - u8 gpi_pin_base; - u8 gpi_pin_end; - u8 gpimapsize_max; - u8 max_row_num; - u8 max_col_num; - u8 row_mask; - u8 col_mask; - u8 col_shift; - u8 c4_extend_cfg; - u8 (*bank) (u8 offset); - u8 (*bit) (u8 offset); - u8 (*reg) (u8 reg); -}; - -struct adp5589_kpad { - struct i2c_client *client; - struct input_dev *input; - const struct adp_constants *var; - unsigned short keycode[ADP5589_KEYMAPSIZE]; - const struct adp5589_gpi_map *gpimap; - unsigned short gpimapsize; - unsigned extend_cfg; - bool is_adp5585; - bool support_row5; -#ifdef CONFIG_GPIOLIB - unsigned char gpiomap[ADP5589_MAXGPIO]; - struct gpio_chip gc; - struct mutex gpio_lock; /* Protect cached dir, dat_out */ - u8 dat_out[3]; - u8 dir[3]; -#endif -}; - -/* - * ADP5589 / ADP5585 derivative / variant handling - */ - - -/* ADP5589 */ - -static unsigned char adp5589_bank(unsigned char offset) -{ - return offset >> 3; -} - -static unsigned char adp5589_bit(unsigned char offset) -{ - return 1u << (offset & 0x7); -} - -static unsigned char adp5589_reg(unsigned char reg) -{ - return reg; -} - -static const struct adp_constants const_adp5589 = { - .maxgpio = ADP5589_MAXGPIO, - .keymapsize = ADP5589_KEYMAPSIZE, - .gpi_pin_row_base = ADP5589_GPI_PIN_ROW_BASE, - .gpi_pin_row_end = ADP5589_GPI_PIN_ROW_END, - .gpi_pin_col_base = ADP5589_GPI_PIN_COL_BASE, - .gpi_pin_base = ADP5589_GPI_PIN_BASE, - .gpi_pin_end = ADP5589_GPI_PIN_END, - .gpimapsize_max = ADP5589_GPIMAPSIZE_MAX, - .c4_extend_cfg = 12, - .max_row_num = ADP5589_MAX_ROW_NUM, - .max_col_num = ADP5589_MAX_COL_NUM, - .row_mask = ADP5589_ROW_MASK, - .col_mask = ADP5589_COL_MASK, - .col_shift = ADP5589_COL_SHIFT, - .bank = adp5589_bank, - .bit = adp5589_bit, - .reg = adp5589_reg, -}; - -/* ADP5585 */ - -static unsigned char adp5585_bank(unsigned char offset) -{ - return offset > ADP5585_MAX_ROW_NUM; -} - -static unsigned char adp5585_bit(unsigned char offset) -{ - return (offset > ADP5585_MAX_ROW_NUM) ? - 1u << (offset - ADP5585_COL_SHIFT) : 1u << offset; -} - -static const unsigned char adp5585_reg_lut[] = { - [ADP5589_GPI_STATUS_A] = ADP5585_GPI_STATUS_A, - [ADP5589_GPI_STATUS_B] = ADP5585_GPI_STATUS_B, - [ADP5589_RPULL_CONFIG_A] = ADP5585_RPULL_CONFIG_A, - [ADP5589_RPULL_CONFIG_B] = ADP5585_RPULL_CONFIG_B, - [ADP5589_RPULL_CONFIG_C] = ADP5585_RPULL_CONFIG_C, - [ADP5589_RPULL_CONFIG_D] = ADP5585_RPULL_CONFIG_D, - [ADP5589_GPI_INT_LEVEL_A] = ADP5585_GPI_INT_LEVEL_A, - [ADP5589_GPI_INT_LEVEL_B] = ADP5585_GPI_INT_LEVEL_B, - [ADP5589_GPI_EVENT_EN_A] = ADP5585_GPI_EVENT_EN_A, - [ADP5589_GPI_EVENT_EN_B] = ADP5585_GPI_EVENT_EN_B, - [ADP5589_GPI_INTERRUPT_EN_A] = ADP5585_GPI_INTERRUPT_EN_A, - [ADP5589_GPI_INTERRUPT_EN_B] = ADP5585_GPI_INTERRUPT_EN_B, - [ADP5589_DEBOUNCE_DIS_A] = ADP5585_DEBOUNCE_DIS_A, - [ADP5589_DEBOUNCE_DIS_B] = ADP5585_DEBOUNCE_DIS_B, - [ADP5589_GPO_DATA_OUT_A] = ADP5585_GPO_DATA_OUT_A, - [ADP5589_GPO_DATA_OUT_B] = ADP5585_GPO_DATA_OUT_B, - [ADP5589_GPO_OUT_MODE_A] = ADP5585_GPO_OUT_MODE_A, - [ADP5589_GPO_OUT_MODE_B] = ADP5585_GPO_OUT_MODE_B, - [ADP5589_GPIO_DIRECTION_A] = ADP5585_GPIO_DIRECTION_A, - [ADP5589_GPIO_DIRECTION_B] = ADP5585_GPIO_DIRECTION_B, - [ADP5589_RESET1_EVENT_A] = ADP5585_RESET1_EVENT_A, - [ADP5589_RESET1_EVENT_B] = ADP5585_RESET1_EVENT_B, - [ADP5589_RESET1_EVENT_C] = ADP5585_RESET1_EVENT_C, - [ADP5589_RESET2_EVENT_A] = ADP5585_RESET2_EVENT_A, - [ADP5589_RESET2_EVENT_B] = ADP5585_RESET2_EVENT_B, - [ADP5589_RESET_CFG] = ADP5585_RESET_CFG, - [ADP5589_PWM_OFFT_LOW] = ADP5585_PWM_OFFT_LOW, - [ADP5589_PWM_OFFT_HIGH] = ADP5585_PWM_OFFT_HIGH, - [ADP5589_PWM_ONT_LOW] = ADP5585_PWM_ONT_LOW, - [ADP5589_PWM_ONT_HIGH] = ADP5585_PWM_ONT_HIGH, - [ADP5589_PWM_CFG] = ADP5585_PWM_CFG, - [ADP5589_LOGIC_1_CFG] = ADP5585_LOGIC_CFG, - [ADP5589_LOGIC_FF_CFG] = ADP5585_LOGIC_FF_CFG, - [ADP5589_LOGIC_INT_EVENT_EN] = ADP5585_LOGIC_INT_EVENT_EN, - [ADP5589_POLL_PTIME_CFG] = ADP5585_POLL_PTIME_CFG, - [ADP5589_PIN_CONFIG_A] = ADP5585_PIN_CONFIG_A, - [ADP5589_PIN_CONFIG_B] = ADP5585_PIN_CONFIG_B, - [ADP5589_PIN_CONFIG_D] = ADP5585_PIN_CONFIG_D, - [ADP5589_GENERAL_CFG] = ADP5585_GENERAL_CFG, - [ADP5589_INT_EN] = ADP5585_INT_EN, -}; - -static unsigned char adp5585_reg(unsigned char reg) -{ - return adp5585_reg_lut[reg]; -} - -static const struct adp_constants const_adp5585 = { - .maxgpio = ADP5585_MAXGPIO, - .keymapsize = ADP5585_KEYMAPSIZE, - .gpi_pin_row_base = ADP5585_GPI_PIN_ROW_BASE, - .gpi_pin_row_end = ADP5585_GPI_PIN_ROW_END, - .gpi_pin_col_base = ADP5585_GPI_PIN_COL_BASE, - .gpi_pin_base = ADP5585_GPI_PIN_BASE, - .gpi_pin_end = ADP5585_GPI_PIN_END, - .gpimapsize_max = ADP5585_GPIMAPSIZE_MAX, - .c4_extend_cfg = 10, - .max_row_num = ADP5585_MAX_ROW_NUM, - .max_col_num = ADP5585_MAX_COL_NUM, - .row_mask = ADP5585_ROW_MASK, - .col_mask = ADP5585_COL_MASK, - .col_shift = ADP5585_COL_SHIFT, - .bank = adp5585_bank, - .bit = adp5585_bit, - .reg = adp5585_reg, -}; - -static int adp5589_read(struct i2c_client *client, u8 reg) -{ - int ret = i2c_smbus_read_byte_data(client, reg); - - if (ret < 0) - dev_err(&client->dev, "Read Error\n"); - - return ret; -} - -static int adp5589_write(struct i2c_client *client, u8 reg, u8 val) -{ - return i2c_smbus_write_byte_data(client, reg, val); -} - -#ifdef CONFIG_GPIOLIB -static int adp5589_gpio_get_value(struct gpio_chip *chip, unsigned off) -{ - struct adp5589_kpad *kpad = gpiochip_get_data(chip); - unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); - unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); - int val; - - mutex_lock(&kpad->gpio_lock); - if (kpad->dir[bank] & bit) - val = kpad->dat_out[bank]; - else - val = adp5589_read(kpad->client, - kpad->var->reg(ADP5589_GPI_STATUS_A) + bank); - mutex_unlock(&kpad->gpio_lock); - - return !!(val & bit); -} - -static void adp5589_gpio_set_value(struct gpio_chip *chip, - unsigned off, int val) -{ - struct adp5589_kpad *kpad = gpiochip_get_data(chip); - unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); - unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); - - guard(mutex)(&kpad->gpio_lock); - - if (val) - kpad->dat_out[bank] |= bit; - else - kpad->dat_out[bank] &= ~bit; - - adp5589_write(kpad->client, kpad->var->reg(ADP5589_GPO_DATA_OUT_A) + - bank, kpad->dat_out[bank]); -} - -static int adp5589_gpio_direction_input(struct gpio_chip *chip, unsigned off) -{ - struct adp5589_kpad *kpad = gpiochip_get_data(chip); - unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); - unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); - - guard(mutex)(&kpad->gpio_lock); - - kpad->dir[bank] &= ~bit; - return adp5589_write(kpad->client, - kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank, - kpad->dir[bank]); -} - -static int adp5589_gpio_direction_output(struct gpio_chip *chip, - unsigned off, int val) -{ - struct adp5589_kpad *kpad = gpiochip_get_data(chip); - unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); - unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); - int error; - - guard(mutex)(&kpad->gpio_lock); - - kpad->dir[bank] |= bit; - - if (val) - kpad->dat_out[bank] |= bit; - else - kpad->dat_out[bank] &= ~bit; - - error = adp5589_write(kpad->client, - kpad->var->reg(ADP5589_GPO_DATA_OUT_A) + bank, - kpad->dat_out[bank]); - if (error) - return error; - - error = adp5589_write(kpad->client, - kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank, - kpad->dir[bank]); - if (error) - return error; - - return 0; -} - -static int adp5589_build_gpiomap(struct adp5589_kpad *kpad, - const struct adp5589_kpad_platform_data *pdata) -{ - bool pin_used[ADP5589_MAXGPIO]; - int n_unused = 0; - int i; - - memset(pin_used, false, sizeof(pin_used)); - - for (i = 0; i < kpad->var->maxgpio; i++) - if (pdata->keypad_en_mask & BIT(i)) - pin_used[i] = true; - - for (i = 0; i < kpad->gpimapsize; i++) - pin_used[kpad->gpimap[i].pin - kpad->var->gpi_pin_base] = true; - - if (kpad->extend_cfg & R4_EXTEND_CFG) - pin_used[4] = true; - - if (kpad->extend_cfg & C4_EXTEND_CFG) - pin_used[kpad->var->c4_extend_cfg] = true; - - if (!kpad->support_row5) - pin_used[5] = true; - - for (i = 0; i < kpad->var->maxgpio; i++) - if (!pin_used[i]) - kpad->gpiomap[n_unused++] = i; - - return n_unused; -} - -static int adp5589_gpio_add(struct adp5589_kpad *kpad) -{ - struct device *dev = &kpad->client->dev; - const struct adp5589_kpad_platform_data *pdata = dev_get_platdata(dev); - const struct adp5589_gpio_platform_data *gpio_data = pdata->gpio_data; - int i, error; - - if (!gpio_data) - return 0; - - kpad->gc.parent = dev; - kpad->gc.ngpio = adp5589_build_gpiomap(kpad, pdata); - if (kpad->gc.ngpio == 0) { - dev_info(dev, "No unused gpios left to export\n"); - return 0; - } - - kpad->gc.direction_input = adp5589_gpio_direction_input; - kpad->gc.direction_output = adp5589_gpio_direction_output; - kpad->gc.get = adp5589_gpio_get_value; - kpad->gc.set = adp5589_gpio_set_value; - kpad->gc.can_sleep = 1; - - kpad->gc.base = gpio_data->gpio_start; - kpad->gc.label = kpad->client->name; - kpad->gc.owner = THIS_MODULE; - - mutex_init(&kpad->gpio_lock); - - error = devm_gpiochip_add_data(dev, &kpad->gc, kpad); - if (error) - return error; - - for (i = 0; i <= kpad->var->bank(kpad->var->maxgpio); i++) { - kpad->dat_out[i] = adp5589_read(kpad->client, kpad->var->reg( - ADP5589_GPO_DATA_OUT_A) + i); - kpad->dir[i] = adp5589_read(kpad->client, kpad->var->reg( - ADP5589_GPIO_DIRECTION_A) + i); - } - - return 0; -} -#else -static inline int adp5589_gpio_add(struct adp5589_kpad *kpad) -{ - return 0; -} -#endif - -static void adp5589_report_switches(struct adp5589_kpad *kpad, - int key, int key_val) -{ - int i; - - for (i = 0; i < kpad->gpimapsize; i++) { - if (key_val == kpad->gpimap[i].pin) { - input_report_switch(kpad->input, - kpad->gpimap[i].sw_evt, - key & KEY_EV_PRESSED); - break; - } - } -} - -static void adp5589_report_events(struct adp5589_kpad *kpad, int ev_cnt) -{ - int i; - - for (i = 0; i < ev_cnt; i++) { - int key = adp5589_read(kpad->client, ADP5589_5_FIFO_1 + i); - int key_val = key & KEY_EV_MASK; - - if (key_val >= kpad->var->gpi_pin_base && - key_val <= kpad->var->gpi_pin_end) { - adp5589_report_switches(kpad, key, key_val); - } else { - input_report_key(kpad->input, - kpad->keycode[key_val - 1], - key & KEY_EV_PRESSED); - } - } -} - -static irqreturn_t adp5589_irq(int irq, void *handle) -{ - struct adp5589_kpad *kpad = handle; - struct i2c_client *client = kpad->client; - int status, ev_cnt; - - status = adp5589_read(client, ADP5589_5_INT_STATUS); - - if (status & OVRFLOW_INT) /* Unlikely and should never happen */ - dev_err(&client->dev, "Event Overflow Error\n"); - - if (status & EVENT_INT) { - ev_cnt = adp5589_read(client, ADP5589_5_STATUS) & KEC; - if (ev_cnt) { - adp5589_report_events(kpad, ev_cnt); - input_sync(kpad->input); - } - } - - adp5589_write(client, ADP5589_5_INT_STATUS, status); /* Status is W1C */ - - return IRQ_HANDLED; -} - -static int adp5589_get_evcode(struct adp5589_kpad *kpad, unsigned short key) -{ - int i; - - for (i = 0; i < kpad->var->keymapsize; i++) - if (key == kpad->keycode[i]) - return (i + 1) | KEY_EV_PRESSED; - - dev_err(&kpad->client->dev, "RESET/UNLOCK key not in keycode map\n"); - - return -EINVAL; -} - -static int adp5589_setup(struct adp5589_kpad *kpad) -{ - struct i2c_client *client = kpad->client; - const struct adp5589_kpad_platform_data *pdata = - dev_get_platdata(&client->dev); - u8 (*reg) (u8) = kpad->var->reg; - unsigned char evt_mode1 = 0, evt_mode2 = 0, evt_mode3 = 0; - unsigned char pull_mask = 0; - int i, ret; - - ret = adp5589_write(client, reg(ADP5589_PIN_CONFIG_A), - pdata->keypad_en_mask & kpad->var->row_mask); - ret |= adp5589_write(client, reg(ADP5589_PIN_CONFIG_B), - (pdata->keypad_en_mask >> kpad->var->col_shift) & - kpad->var->col_mask); - - if (!kpad->is_adp5585) - ret |= adp5589_write(client, ADP5589_PIN_CONFIG_C, - (pdata->keypad_en_mask >> 16) & 0xFF); - - if (!kpad->is_adp5585 && pdata->en_keylock) { - ret |= adp5589_write(client, ADP5589_UNLOCK1, - pdata->unlock_key1); - ret |= adp5589_write(client, ADP5589_UNLOCK2, - pdata->unlock_key2); - ret |= adp5589_write(client, ADP5589_UNLOCK_TIMERS, - pdata->unlock_timer & LTIME_MASK); - ret |= adp5589_write(client, ADP5589_LOCK_CFG, LOCK_EN); - } - - for (i = 0; i < KEYP_MAX_EVENT; i++) - ret |= adp5589_read(client, ADP5589_5_FIFO_1 + i); - - for (i = 0; i < pdata->gpimapsize; i++) { - unsigned short pin = pdata->gpimap[i].pin; - - if (pin <= kpad->var->gpi_pin_row_end) { - evt_mode1 |= BIT(pin - kpad->var->gpi_pin_row_base); - } else { - evt_mode2 |= - BIT(pin - kpad->var->gpi_pin_col_base) & 0xFF; - if (!kpad->is_adp5585) - evt_mode3 |= - BIT(pin - kpad->var->gpi_pin_col_base) >> 8; - } - } - - if (pdata->gpimapsize) { - ret |= adp5589_write(client, reg(ADP5589_GPI_EVENT_EN_A), - evt_mode1); - ret |= adp5589_write(client, reg(ADP5589_GPI_EVENT_EN_B), - evt_mode2); - if (!kpad->is_adp5585) - ret |= adp5589_write(client, - reg(ADP5589_GPI_EVENT_EN_C), - evt_mode3); - } - - if (pdata->pull_dis_mask & pdata->pullup_en_100k & - pdata->pullup_en_300k & pdata->pulldown_en_300k) - dev_warn(&client->dev, "Conflicting pull resistor config\n"); - - for (i = 0; i <= kpad->var->max_row_num; i++) { - unsigned int val = 0, bit = BIT(i); - if (pdata->pullup_en_300k & bit) - val = 0; - else if (pdata->pulldown_en_300k & bit) - val = 1; - else if (pdata->pullup_en_100k & bit) - val = 2; - else if (pdata->pull_dis_mask & bit) - val = 3; - - pull_mask |= val << (2 * (i & 0x3)); - - if (i % 4 == 3 || i == kpad->var->max_row_num) { - ret |= adp5589_write(client, reg(ADP5585_RPULL_CONFIG_A) - + (i >> 2), pull_mask); - pull_mask = 0; - } - } - - for (i = 0; i <= kpad->var->max_col_num; i++) { - unsigned int val = 0, bit = BIT(i + kpad->var->col_shift); - if (pdata->pullup_en_300k & bit) - val = 0; - else if (pdata->pulldown_en_300k & bit) - val = 1; - else if (pdata->pullup_en_100k & bit) - val = 2; - else if (pdata->pull_dis_mask & bit) - val = 3; - - pull_mask |= val << (2 * (i & 0x3)); - - if (i % 4 == 3 || i == kpad->var->max_col_num) { - ret |= adp5589_write(client, - reg(ADP5585_RPULL_CONFIG_C) + - (i >> 2), pull_mask); - pull_mask = 0; - } - } - - if (pdata->reset1_key_1 && pdata->reset1_key_2 && pdata->reset1_key_3) { - ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_A), - adp5589_get_evcode(kpad, - pdata->reset1_key_1)); - ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_B), - adp5589_get_evcode(kpad, - pdata->reset1_key_2)); - ret |= adp5589_write(client, reg(ADP5589_RESET1_EVENT_C), - adp5589_get_evcode(kpad, - pdata->reset1_key_3)); - kpad->extend_cfg |= R4_EXTEND_CFG; - } - - if (pdata->reset2_key_1 && pdata->reset2_key_2) { - ret |= adp5589_write(client, reg(ADP5589_RESET2_EVENT_A), - adp5589_get_evcode(kpad, - pdata->reset2_key_1)); - ret |= adp5589_write(client, reg(ADP5589_RESET2_EVENT_B), - adp5589_get_evcode(kpad, - pdata->reset2_key_2)); - kpad->extend_cfg |= C4_EXTEND_CFG; - } - - if (kpad->extend_cfg) { - ret |= adp5589_write(client, reg(ADP5589_RESET_CFG), - pdata->reset_cfg); - ret |= adp5589_write(client, reg(ADP5589_PIN_CONFIG_D), - kpad->extend_cfg); - } - - ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_A), - pdata->debounce_dis_mask & kpad->var->row_mask); - - ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_B), - (pdata->debounce_dis_mask >> kpad->var->col_shift) - & kpad->var->col_mask); - - if (!kpad->is_adp5585) - ret |= adp5589_write(client, reg(ADP5589_DEBOUNCE_DIS_C), - (pdata->debounce_dis_mask >> 16) & 0xFF); - - ret |= adp5589_write(client, reg(ADP5589_POLL_PTIME_CFG), - pdata->scan_cycle_time & PTIME_MASK); - ret |= adp5589_write(client, ADP5589_5_INT_STATUS, - (kpad->is_adp5585 ? 0 : LOGIC2_INT) | - LOGIC1_INT | OVRFLOW_INT | - (kpad->is_adp5585 ? 0 : LOCK_INT) | - GPI_INT | EVENT_INT); /* Status is W1C */ - - ret |= adp5589_write(client, reg(ADP5589_GENERAL_CFG), - INT_CFG | OSC_EN | CORE_CLK(3)); - ret |= adp5589_write(client, reg(ADP5589_INT_EN), - OVRFLOW_IEN | GPI_IEN | EVENT_IEN); - - if (ret < 0) { - dev_err(&client->dev, "Write Error\n"); - return ret; - } - - return 0; -} - -static void adp5589_report_switch_state(struct adp5589_kpad *kpad) -{ - int gpi_stat_tmp, pin_loc; - int i; - int gpi_stat1 = adp5589_read(kpad->client, - kpad->var->reg(ADP5589_GPI_STATUS_A)); - int gpi_stat2 = adp5589_read(kpad->client, - kpad->var->reg(ADP5589_GPI_STATUS_B)); - int gpi_stat3 = !kpad->is_adp5585 ? - adp5589_read(kpad->client, ADP5589_GPI_STATUS_C) : 0; - - for (i = 0; i < kpad->gpimapsize; i++) { - unsigned short pin = kpad->gpimap[i].pin; - - if (pin <= kpad->var->gpi_pin_row_end) { - gpi_stat_tmp = gpi_stat1; - pin_loc = pin - kpad->var->gpi_pin_row_base; - } else if ((pin - kpad->var->gpi_pin_col_base) < 8) { - gpi_stat_tmp = gpi_stat2; - pin_loc = pin - kpad->var->gpi_pin_col_base; - } else { - gpi_stat_tmp = gpi_stat3; - pin_loc = pin - kpad->var->gpi_pin_col_base - 8; - } - - if (gpi_stat_tmp < 0) { - dev_err(&kpad->client->dev, - "Can't read GPIO_DAT_STAT switch %d, default to OFF\n", - pin); - gpi_stat_tmp = 0; - } - - input_report_switch(kpad->input, - kpad->gpimap[i].sw_evt, - !(gpi_stat_tmp & BIT(pin_loc))); - } - - input_sync(kpad->input); -} - -static int adp5589_keypad_add(struct adp5589_kpad *kpad, unsigned int revid) -{ - struct i2c_client *client = kpad->client; - const struct adp5589_kpad_platform_data *pdata = - dev_get_platdata(&client->dev); - struct input_dev *input; - unsigned int i; - int error; - - if (!((pdata->keypad_en_mask & kpad->var->row_mask) && - (pdata->keypad_en_mask >> kpad->var->col_shift)) || - !pdata->keymap) { - dev_err(&client->dev, "no rows, cols or keymap from pdata\n"); - return -EINVAL; - } - - if (pdata->keymapsize != kpad->var->keymapsize) { - dev_err(&client->dev, "invalid keymapsize\n"); - return -EINVAL; - } - - if (!pdata->gpimap && pdata->gpimapsize) { - dev_err(&client->dev, "invalid gpimap from pdata\n"); - return -EINVAL; - } - - if (pdata->gpimapsize > kpad->var->gpimapsize_max) { - dev_err(&client->dev, "invalid gpimapsize\n"); - return -EINVAL; - } - - for (i = 0; i < pdata->gpimapsize; i++) { - unsigned short pin = pdata->gpimap[i].pin; - - if (pin < kpad->var->gpi_pin_base || - pin > kpad->var->gpi_pin_end) { - dev_err(&client->dev, "invalid gpi pin data\n"); - return -EINVAL; - } - - if (BIT(pin - kpad->var->gpi_pin_row_base) & - pdata->keypad_en_mask) { - dev_err(&client->dev, "invalid gpi row/col data\n"); - return -EINVAL; - } - } - - if (!client->irq) { - dev_err(&client->dev, "no IRQ?\n"); - return -EINVAL; - } - - input = devm_input_allocate_device(&client->dev); - if (!input) - return -ENOMEM; - - kpad->input = input; - - input->name = client->name; - input->phys = "adp5589-keys/input0"; - input->dev.parent = &client->dev; - - input_set_drvdata(input, kpad); - - input->id.bustype = BUS_I2C; - input->id.vendor = 0x0001; - input->id.product = 0x0001; - input->id.version = revid; - - input->keycodesize = sizeof(kpad->keycode[0]); - input->keycodemax = pdata->keymapsize; - input->keycode = kpad->keycode; - - memcpy(kpad->keycode, pdata->keymap, - pdata->keymapsize * input->keycodesize); - - kpad->gpimap = pdata->gpimap; - kpad->gpimapsize = pdata->gpimapsize; - - /* setup input device */ - __set_bit(EV_KEY, input->evbit); - - if (pdata->repeat) - __set_bit(EV_REP, input->evbit); - - for (i = 0; i < input->keycodemax; i++) - if (kpad->keycode[i] <= KEY_MAX) - __set_bit(kpad->keycode[i], input->keybit); - __clear_bit(KEY_RESERVED, input->keybit); - - if (kpad->gpimapsize) - __set_bit(EV_SW, input->evbit); - for (i = 0; i < kpad->gpimapsize; i++) - __set_bit(kpad->gpimap[i].sw_evt, input->swbit); - - error = input_register_device(input); - if (error) { - dev_err(&client->dev, "unable to register input device\n"); - return error; - } - - error = devm_request_threaded_irq(&client->dev, client->irq, - NULL, adp5589_irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - client->dev.driver->name, kpad); - if (error) { - dev_err(&client->dev, "unable to request irq %d\n", client->irq); - return error; - } - - return 0; -} - -static void adp5589_clear_config(void *data) -{ - struct adp5589_kpad *kpad = data; - - adp5589_write(kpad->client, kpad->var->reg(ADP5589_GENERAL_CFG), 0); -} - -static int adp5589_probe(struct i2c_client *client) -{ - const struct i2c_device_id *id = i2c_client_get_device_id(client); - struct adp5589_kpad *kpad; - const struct adp5589_kpad_platform_data *pdata = - dev_get_platdata(&client->dev); - unsigned int revid; - int error, ret; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA)) { - dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); - return -EIO; - } - - if (!pdata) { - dev_err(&client->dev, "no platform data?\n"); - return -EINVAL; - } - - kpad = devm_kzalloc(&client->dev, sizeof(*kpad), GFP_KERNEL); - if (!kpad) - return -ENOMEM; - - kpad->client = client; - - switch (id->driver_data) { - case ADP5585_02: - kpad->support_row5 = true; - fallthrough; - case ADP5585_01: - kpad->is_adp5585 = true; - kpad->var = &const_adp5585; - break; - case ADP5589: - kpad->support_row5 = true; - kpad->var = &const_adp5589; - break; - } - - error = devm_add_action_or_reset(&client->dev, adp5589_clear_config, - kpad); - if (error) - return error; - - ret = adp5589_read(client, ADP5589_5_ID); - if (ret < 0) - return ret; - - revid = (u8) ret & ADP5589_5_DEVICE_ID_MASK; - - if (pdata->keymapsize) { - error = adp5589_keypad_add(kpad, revid); - if (error) - return error; - } - - error = adp5589_setup(kpad); - if (error) - return error; - - if (kpad->gpimapsize) - adp5589_report_switch_state(kpad); - - error = adp5589_gpio_add(kpad); - if (error) - return error; - - dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq); - return 0; -} - -static int adp5589_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adp5589_kpad *kpad = i2c_get_clientdata(client); - - if (kpad->input) - disable_irq(client->irq); - - return 0; -} - -static int adp5589_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adp5589_kpad *kpad = i2c_get_clientdata(client); - - if (kpad->input) - enable_irq(client->irq); - - return 0; -} - -static DEFINE_SIMPLE_DEV_PM_OPS(adp5589_dev_pm_ops, adp5589_suspend, adp5589_resume); - -static const struct i2c_device_id adp5589_id[] = { - {"adp5589-keys", ADP5589}, - {"adp5585-keys", ADP5585_01}, - {"adp5585-02-keys", ADP5585_02}, /* Adds ROW5 to ADP5585 */ - {} -}; - -MODULE_DEVICE_TABLE(i2c, adp5589_id); - -static struct i2c_driver adp5589_driver = { - .driver = { - .name = KBUILD_MODNAME, - .pm = pm_sleep_ptr(&adp5589_dev_pm_ops), - }, - .probe = adp5589_probe, - .id_table = adp5589_id, -}; - -module_i2c_driver(adp5589_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("ADP5589/ADP5585 Keypad driver"); From patchwork Thu Mar 13 14:19:31 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: 873650 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 27378267B91; Thu, 13 Mar 2025 14:19: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=1741875559; cv=none; b=HLgj88mvdb32OheoFoKT+eOiY3ANkGgeDq0TQY1MuL7qIrWTLxtqr2OVcZqaenaSAy+1fl7aoj5DRdDfKWUPc15csmDfjnqGouxfHZwC47gm2papBpqRiuL6V7IYx6qdSlzkOgGPaCc5ijTDF2iByn7tSG5iVx7CKGnxdCVe9X0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875559; c=relaxed/simple; bh=DOWRjEQd28uwnO0cH4/p2K3VZkyb7ycxqZy8dbXqttw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nNu6YRKyRVKhBpijLEWef3p+cEwooxp3MsB/hpHRLVYkb6GPkzkEksjxwXbdQImUJdRt/W6Q2S6It8cDC+/PLITl/HJFgh6onzq1bxeZyYsvpRDDwkqybNpyKq5hIP0xt6kA4Ya+bhiWzAuMikklg53Rs8GgNsQxXDVQbl7xSgU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MvFp6xQ7; 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="MvFp6xQ7" Received: by smtp.kernel.org (Postfix) with ESMTPS id 624CBC2BCF6; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875558; bh=DOWRjEQd28uwnO0cH4/p2K3VZkyb7ycxqZy8dbXqttw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=MvFp6xQ7TrCQJZ08MfQt6HmJM+iMq2P5LvXQWUUVkWqUrugXjfdGnTAfOZLFqolRK IfKl8/60zdcUk/V+7dYTWmlUesXX8ivEA3M7JYocK4xw63PxtL8fdvPx8mpGF41Vcx dnq+Vyjs0RLdqFwU3mQAPMgHOnhFbgLSdhENfWBBHzoM7X0yfvsKx/HYFevz+mN/Xw VzjvM90rssRkioNSIzFBqaxIoTDWYLA+wyGLWRhIQpNVicKIiSq8QOJSaWB6hbH8H3 lWFx08uO0g1vYBkkoG5duxQhkWCP/TqnomyFdXqQPKUtoz7pYXr7LK0ff7aP9gAsMe Ox9BUoWFCBjHg== 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 5684DC282EC; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:31 +0000 Subject: [PATCH 14/18] mfd: adp5585: support getting vdd regulator Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-14-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875561; l=1028; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=trpzpm4IMbeoKlpJzcTFH6plumlFIe+Jo8NI6LqOEKE=; b=9BrNzNjZ8ytgDtwKpf2aEtlVOlEt5myJIiByCaPzav+fDCKb1sV4h8KczvxGzXDhv+sPlJiCD glnRgsoMs8XAAT6gi6AmEY62RyVBloCuEt0+1OHiMQIqesS2EoB7cLP 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 a96de4e6a3a12e2c91528835c2061795e6ff3ed0..8f95a02661880477e5eddb4248e92ee1bc69d674 100644 --- a/drivers/mfd/adp5585.c +++ b/drivers/mfd/adp5585.c @@ -17,6 +17,7 @@ #include #include #include +#include #include static const struct mfd_cell adp5585_devs[] = { @@ -848,6 +849,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 Thu Mar 13 14:19: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: 873649 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 54604268FE2; Thu, 13 Mar 2025 14:19: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=1741875559; cv=none; b=gEuXL8XzReq5B3LyWkCPYKnAKTTv+u8XpTnk6S6GT2qN6ET/D7wJrX0MdMo5dgEvJraAMftXD7H4goYtqGs77qwxCMK/gKpe6OCaHglgMPvAyFZo2laez0cAsFzVGjrRpkE1qN/m7xsAp8bXzLrEr/+fZSfds5aMsM88A7Qt3bM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875559; c=relaxed/simple; bh=HTZtKcPE/KmLhTONUSP12PIgECGY/rxdeux1UJD5SzM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=m6XLA03yu/X5CFlUfUMn4YH9Ma0UdUT7C+8kLr3wNmaizgFwV6sVXKtQKN75wFu1PIx6xUP/9aU8oHWBETwNV8YQZsP/sLGjswRc1J7aF6GlUJS9eHzvzNkSYA7YCLlCz0ZQMN2jkVwir18PAHyRGrW/6tRYbnNrSm5/SekiAEs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FaOr28aX; 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="FaOr28aX" Received: by smtp.kernel.org (Postfix) with ESMTPS id 7A897C4AF11; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875558; bh=HTZtKcPE/KmLhTONUSP12PIgECGY/rxdeux1UJD5SzM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=FaOr28aXXq5n6fADEcWaXBezw78Plia0WjMpZA6VHl6iLj3jDoIeKqw4Q6NlKhDl1 naPYP85YKgHDFPef4jew7S3ApB8lzGCwgFRgJFblVSpPvhOCrGkvUTAuL214l+HA9y V7gXJlJYhDUae5rPoEexMMRNWc0+OX+H3RPkrt06+mx8Es3GKnkOPqOfzeRo3aTqWP ggjFGmbNHmmjDMNKoQrKJS8pXjo7Dc5D+y/DBdUiiwB/qV/pqQMEWO0Hk8Txu+SEmr wg9sJ2bheCRPHHqD+HK0ltDXMo4/CaJ3hmm0gtQULvLbSJnoLLnydwW6GNqkxctovn 5qbs8qGzDF7Gw== 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 67157C28B2E; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:32 +0000 Subject: [PATCH 15/18] dt-bindings: mfd: adp5585: document reset gpio Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-15-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875561; l=1046; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=RZgpAeQ47IAlMhn5Pqw+gcN/6fM2CbPkY3yNF9wFGcw=; b=R4mB0yuWY/DXUTGIo92U4KKoBaqk/uH940J7JYXdGbEPw5qWOV92ru6vk3WbsvN85iaSXDRpg rs/ZeUXAqMVDUwfodlMCWWiZKwze3xZ3n0xgRr4ouDVWr1NAjbsoweT 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á Add a reset gpio property. Note that for the adp5585-01 models, the reset pin is used as the additional ROW5 which means there's no reset. Signed-off-by: Nuno Sá --- Documentation/devicetree/bindings/mfd/adi,adp5585.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml b/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml index e976c9240df79afae1d0949e6ac91d477bfaceef..20488af1563369b0ef60e8b55ad660a35623039c 100644 --- a/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml +++ b/Documentation/devicetree/bindings/mfd/adi,adp5585.yaml @@ -39,6 +39,9 @@ properties: vdd-supply: true + reset-gpios: + maxItems: 1 + gpio-controller: true '#gpio-cells': @@ -167,6 +170,7 @@ allOf: adi,unlock-keys: false adi,unlock-trigger-sec: false gpio-reserved-ranges: false + reset-gpios: false adi,keypad-pins: minItems: 2 maxItems: 11 From patchwork Thu Mar 13 14:19:33 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: 873244 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 69D82268FF4; Thu, 13 Mar 2025 14:19: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=1741875559; cv=none; b=JfmD04oWFArrE/MQmUQx7aiRpMC936xFDxxti6nAc/cT0bTabRE0ehJ6PHSgG2b4u8NHlDHqGUR6joZWV4SdSuHbnmsv0z9Biu90YvdHA0w0bZfNKaCPkEgQkBaYcjag6NrSDfMa8KXBKgyVmm1IB21oVB3vTmFRg8HM5LHdc4A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875559; c=relaxed/simple; bh=tt4Utqobtry0elLkZy/8b5K7bXpZf4SKtlf6QE2iyHY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tFQh1XQgh1IvhJ4eY7OwHutAvajZX0OmDFmiHBrW8YHQEMGfNhnpsA6V7bW/cCYUMLDBlamcp7l21ZN0f6gUfQoX9JWTSH9zswmaIsfSIx8qbUU4PuQ0raoQW+ee6dF6fRuQxaMs1NhHoBpMSVsGvosLLeGXIhJLJ640wLpyS5c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jpHwUlTM; 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="jpHwUlTM" Received: by smtp.kernel.org (Postfix) with ESMTPS id 90A70C4AF13; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875558; bh=tt4Utqobtry0elLkZy/8b5K7bXpZf4SKtlf6QE2iyHY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=jpHwUlTMx8wrYMdV+VqVG6PjmFcO10IvcLqrm/pQP/SCdiRbbAxYrwRLBY+KiNhY/ 7WaAeRjUBk4UP6AkvktpTBlfeVgScdlMmnNbBDg2QI3s1GMRC2wdAYscNga/EAmCxr fEx/X80YSNmeVeIFIdgpegfUMUReN/LyXbPIi5yLlJbC3+rS3mtogRefmKSRfg+oeg gXh9MRxZX4d9uFZ2PY2C9SLolobWkIs3sWidIZ5vEsIdcMbSQSyNUjDmfGIYQ2YaFS o5X8SE9Lqb5njOBfq1cAWjvZ5URYkJ4vcCaqP4vRVSrXsL2Bb7pHs22UA6CUx5Uvp4 /+i7NJapG7bww== 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 7D038C282DE; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:33 +0000 Subject: [PATCH 16/18] mfd: adp5585: add support for a reset pin Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-16-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875562; l=1359; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=FjlFHqph7I3VSZKc1cRPYbSwbj1DPL1FekJPsO/UbRs=; b=nbmzJMHYSHEI/3Jyqjaq0WzUemO9px1DIXtBLRv34BbbZhpb6GiX4/cMODjbx1Dys5b1pBq7y LRn4NSUcIQJDNcO4LgX1FxifvcHwNkO+JXlsOO2bVaNyPRm+7OAm5/c 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 8f95a02661880477e5eddb4248e92ee1bc69d674..dd8c4221cacd5bbff3179c48015401279bbf3d33 100644 --- a/drivers/mfd/adp5585.c +++ b/drivers/mfd/adp5585.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -832,6 +833,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; @@ -853,6 +855,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), From patchwork Thu Mar 13 14:19:34 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: 873648 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 69DEA268FF6; Thu, 13 Mar 2025 14:19: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=1741875559; cv=none; b=EH5Hbk/ugMVuUKUIZqp+FSJ8cCIqXLpLi28d/uZRdOfVmakYKjN7BwNbodvz9N5lUhEd1I85Xlm6nqQZQ895onz73Tvtgt6rPQbUrX54f3rK6iByUjzIIgsuzNyeMLaFaKSdLsXIuyTkGWycDDHI6nWE0AovcyrMUqUYm9YU+6c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875559; c=relaxed/simple; bh=uYXjR3iB4JAIRXA3YSj8ha9P/j2R0WJud1vpenZ2YtA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=uw3J4iwU9JYHytVQiYt/RMFWtDWShUBZhmkZjCZ+OhrOlWEqkPFW4BBReBxEdHi8yADxcTukL9q5MoVOJwdlaoCSX95EP1K0mI1fcLQs3fN018aS4yl7k8sprHeAUeGL2kqr3wk39SSqfNC/BK3EfmBTJ6jMcj4tiybjXUOcyNg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=StMiNiQs; 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="StMiNiQs" Received: by smtp.kernel.org (Postfix) with ESMTPS id 9A223C4DDE0; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875558; bh=uYXjR3iB4JAIRXA3YSj8ha9P/j2R0WJud1vpenZ2YtA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=StMiNiQszfQr+DjELk6VmXOlasloeNWLCy2iHGTTS8l3A7/P9BzVI9uoGNdEclHgJ ESeFguWCAlO/qmWE7Ufdwx/BIvCNzM513R8WeZ5sX+7/93g3J/lxDOTDpbMUKvTsCO DFQ9zOjukIxTLPFXvEUYTezvc4p3yp5YBw4SM8y9zrOAXRA+z3n3Z33iMKVwDAsfct +J1xiIhRq4w+2oekt+TZRN0V6j5F23/f2u/3AULwDGwy1qZMY/J37EQWIkkJxPfKKS jIzhce1I0j2562S56cIc/WIUEQw1MqUdcGEMoWBKk3ulCoI6z/BlNCMyyf5kEnpX87 COzPpzTY9xDCQ== 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 8E82CC282EC; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:34 +0000 Subject: [PATCH 17/18] pwm: adp5585: make sure to include mod_devicetable.h Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-17-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875562; l=672; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=tqFurroQfEZIIAKBp0UvBVXq9bErS1HNimmEhHkQKV0=; b=hfpdLUVm6u/hFamM0DfVIZ4hdcQUAfz3yq26VEMBtbydRqYE8myLuJ5SvqlaRxXxKjvU0KHV+ bbhXliKvK+0Cwhh4nE1fXqvUwLEn0i2NxZQQLFNdEciZnWpxRD6QBE2 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á Explicitly include mod_devicetable.h for struct platform_device_id. Signed-off-by: Nuno Sá --- drivers/pwm/pwm-adp5585.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pwm/pwm-adp5585.c b/drivers/pwm/pwm-adp5585.c index cc8ac8f9e5669b4ffca06d4117a29f030393f48f..85308257724a338da4d2416c8d01e48e08bd0856 100644 --- a/drivers/pwm/pwm-adp5585.c +++ b/drivers/pwm/pwm-adp5585.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include From patchwork Thu Mar 13 14:19:35 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: 873243 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 949602690D1; Thu, 13 Mar 2025 14:19: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=1741875559; cv=none; b=uPzPnGlMKy+yRWFoekOtwWNempIQGpZkXniDUFpK9o+6CNhbxOvgkPI4tJgWAv2/o4yIUzL+cfyZNU3xHO7MwG7Motw4L8kFCXAXvuzB1cWaFovNNcAqxpecwZK/8y86nh4GL7tbOR9k+i9s68tdfE4ZQqlBGKmqvk8atMmrgic= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741875559; c=relaxed/simple; bh=uXW7xk7RjFtwz9/eHiqWTp3uEA/z2hCFoeDIFF3e+Yw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CQZrpW3MWAUYVTHe8RTtwlml/KhBgJh2ujrYt/E365W9YZibB67iycP6iraOjJ35JJbEq8LRYVovi6dfQVMKl+aHOlDJszdHENWp5XUmrVejFYEakWFQD6yb4QkIN1oKWmzdt86NNfNsQe5PvTVQTl2YVNToaBsvrkmZRtRo68o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tAgn0JYV; 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="tAgn0JYV" Received: by smtp.kernel.org (Postfix) with ESMTPS id AD971C113D0; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1741875558; bh=uXW7xk7RjFtwz9/eHiqWTp3uEA/z2hCFoeDIFF3e+Yw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=tAgn0JYVAKNiuSyQ0EupMSGNxfs32lsn4MybtsBdtn/PQ4MEMQFSSkfvG4LRkYcVH Wb4uc/0U/O3/fME9VO5bZli7QrSIrBEpg5na7/V6FiA73FtUs8/8mNEw5bS/bJKZwz sST9T41IajEVwul1W/7G93aK0C80GJFegg96dJbCzlcPe0sZ46pQXZG2mMBUepdOCg 5uCtfXrcuq/V8ziD7927KA13HsvIl5AaVzKGYaEbKm7pGsuqeMEVrJb/JFpN4sUTbe g04oRYPrPbyEHXOfWGznqtWpvrQ3SczBbpIIRb3HCBMXrPcRHidI2N6JV4Qivia4KB fNbHh/xW703gA== 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 9E881C35FF3; Thu, 13 Mar 2025 14:19:18 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Thu, 13 Mar 2025 14:19:35 +0000 Subject: [PATCH 18/18] gpio: adp5585: make sure to include mod_devicetable.h Precedence: bulk X-Mailing-List: linux-gpio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250313-dev-adp5589-fw-v1-18-20e80d4bd4ea@analog.com> References: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@analog.com> In-Reply-To: <20250313-dev-adp5589-fw-v1-0-20e80d4bd4ea@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=1741875562; l=689; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=P0ZkoXH3VRNpqlqHd8qSMhJYSdP+cbx0zZzSEvnRg0w=; b=BtgG+iLMEWirXxzDnVoHGskZFy5DrxlCP7h8aBoe5Nne4DICyQH79iKwBOxKDUlFVDK7UHvny /mWDby33fYwBcWu3FuU/aDfzh8E+/0IsMuZ6rJxwVJTElDj/Vjov7q1 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á Explicitly include mod_devicetable.h for struct platform_device_id. Signed-off-by: Nuno Sá --- drivers/gpio/gpio-adp5585.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-adp5585.c b/drivers/gpio/gpio-adp5585.c index cfd0aab1f7414f76287714eda44184c615491194..faeb6243bfb40007517d4484621a137aa2f1bd55 100644 --- a/drivers/gpio/gpio-adp5585.c +++ b/drivers/gpio/gpio-adp5585.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include