From patchwork Thu Apr 18 01:32:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Peng Fan (OSS)" X-Patchwork-Id: 13634051 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id DB8A1C001CC for ; Thu, 18 Apr 2024 01:25:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Cc:To:In-Reply-To: References:Message-Id:Subject:Date:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=e0DIpwe1cfUSziWyx8/FWqmWZ8qaEVa3LK3dNBykAVA=; b=3ojyTLDJGTy7ONl3+VKXKHtxx2 gAAEvig11coCtjW9PNthWxqrBfil4qjKxFjVlitfrMVTJ1qSPqXmT5E3Hzwv9nMXJOjsCmca2mrhJ DPEBNc+QZDbAQkjf6FDc8Rd9lm9DBnKdvYRj1XHzKO9lDB+Rp34tuNOQesQhCbB+a3ivLs+U4ipRw uw3Ee1LhXlcnX25vjA0lEx3mTe+2UdhsTxVk3szCjSPWsj5FwQPolNSy0O3Qe8j+P85TWR6WdXIJv DHXqKh/8ZcwzAjJlbJNhMGVGhthmeVDaTd8W6q2cS7X/M4h01iG3NrfjqTIzHVN2ykTBoSNCs+2Zl 7t2H+1UQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rxGWH-00000000YZk-3H6t; Thu, 18 Apr 2024 01:24:57 +0000 Received: from mail-db8eur05on2062e.outbound.protection.outlook.com ([2a01:111:f400:7e1a::62e] helo=EUR05-DB8-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rxGW8-00000000YTd-3avy for linux-arm-kernel@lists.infradead.org; Thu, 18 Apr 2024 01:24:50 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=PP8eVU9tQSmdQY27I6kCokUWWv+MeneGiwBzxV/y4KS0yAW8EoyzJQHENjEBys7cF1gK0CHDt46U9NIlNCgHpGZhnghjky0x3uIjcHGcwDpC/aYF1v6R2kGb0AlUlusELgPUzpARieiTxqv85Cjrrj7nkEA9kmwLwurg0oipAPrrmF/KGYpq82mN+fV5i4Dss+r+NdbP1fgcH5jXa22vbkgPa3RI9Vo92tLtLrpmSEnxDET3Ou3K4A96stUAhCtntr9d93f4TqPiZn1mk5gyBmGGt/qVlamuOMqVWrCSMbiHUxSu8JBBX54swr+bx3qBIGGc2JXA/JMEGmKOsp69+w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=y32EPUygoezOrwpSdGDK5Cezq+RoDLA6Ci/XuseYkwM=; b=gu6W/oy+Clkvt9+gj6WHbJHe1ZZrefbjXJ2Gs6iBsWnL/OhZi0VRxTTmSViUeEVlmhMTu2832Jfae1E38X5UMuCHKTbLvMZE0qJTn+Ysn/8vI+QLyBuNiGwqfGRVYSLPOiyEg4MDAgy4lM9otldHmb4FSEwDGpkT71GnC4H4Qgi7X7hesAQop6QHzHTrt6n9gFBrL5ny+LF6G6E8fEtG5GdMLDAsL+DB3Vpzx21+ZxHcheRf2H7Pq2ZqETOt2UqFKll/XSDJ6uN4khdaOI4pczs9x8DLGdoUiaIYtUgG1dL2aGpn3wFXxNhRvI5k8qW5wIYn7fnWu9Y9vbf5sz2/DQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oss.nxp.com; dmarc=pass action=none header.from=oss.nxp.com; dkim=pass header.d=oss.nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NXP1.onmicrosoft.com; s=selector2-NXP1-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=y32EPUygoezOrwpSdGDK5Cezq+RoDLA6Ci/XuseYkwM=; b=PMDumWxwNmd5rq/S0BvKVcAWRrbbN1ME3ujEixkcX2GaTGeW5MNMURK8ja1IpVQNNOxzYGrCVz/mo3htpSwisWnzz/c9zySCy9TXJeo6SpNmGnlDdGGacTbquXGj0THq1ISlOYJznBmGgw24uF6vFfmoDVQQ5xa4F1//CR2Ajp0= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=oss.nxp.com; Received: from DU0PR04MB9417.eurprd04.prod.outlook.com (2603:10a6:10:358::11) by AS1PR04MB9264.eurprd04.prod.outlook.com (2603:10a6:20b:4c4::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7452.50; Thu, 18 Apr 2024 01:24:36 +0000 Received: from DU0PR04MB9417.eurprd04.prod.outlook.com ([fe80::d30b:44e7:e78e:662d]) by DU0PR04MB9417.eurprd04.prod.outlook.com ([fe80::d30b:44e7:e78e:662d%4]) with mapi id 15.20.7452.049; Thu, 18 Apr 2024 01:24:36 +0000 From: "Peng Fan (OSS)" Date: Thu, 18 Apr 2024 09:32:28 +0800 Subject: [PATCH v11 1/4] firmware: arm_scmi: introduce helper get_max_msg_size Message-Id: <20240418-pinctrl-scmi-v11-1-499dca9864a7@nxp.com> References: <20240418-pinctrl-scmi-v11-0-499dca9864a7@nxp.com> In-Reply-To: <20240418-pinctrl-scmi-v11-0-499dca9864a7@nxp.com> To: Sudeep Holla , Cristian Marussi , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Linus Walleij , Dan Carpenter Cc: Dhruva Gole , Andy Shevchenko , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-gpio@vger.kernel.org, Peng Fan X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1713403963; l=2695; i=peng.fan@nxp.com; s=20230812; h=from:subject:message-id; bh=fC1f9Mz+AZ7lC+TNU94i2E/beyKrQPUiXgoBP0YzZ74=; b=uvGNPiYqgihRcYCo3u01MEoYWEnTApbl6WtoFdgkeg2yPSLHnNnHKxaYow7E0JYtw3Y2Ph5oJ VMjur4H9GOMBVLegt5x3bUzYI4sZ0oWyo+cl7HVxPTP1d2auoz/7RJj X-Developer-Key: i=peng.fan@nxp.com; a=ed25519; pk=I4sJg7atIT1g63H7bb5lDRGR2gJW14RKDD0wFL8TT1g= X-ClientProxiedBy: SG2PR03CA0116.apcprd03.prod.outlook.com (2603:1096:4:91::20) To DU0PR04MB9417.eurprd04.prod.outlook.com (2603:10a6:10:358::11) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DU0PR04MB9417:EE_|AS1PR04MB9264:EE_ X-MS-Office365-Filtering-Correlation-Id: 788082d5-b6c1-4ac7-0827-08dc5f464f40 X-MS-Exchange-SharedMailbox-RoutingAgent-Processed: True X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: dIbXlh/XHPprriWeHssC8P2/XQGG2ou4/k3PeLQfG/MChKG12So4vKxnfVhXsivb0jog2ilYSKbexijEFSqww0H1TDkOhzzhIPwtaDzlEpK9+w/sDUYPF9MyyBvULZG+oHgqkrgdcDKZnQ66TNEyR/jXfA9eXRSHJ3s5Enjj+GfSlCdFwg/9GFWM5lEg5D/54ypT1364fviJEi7AbDP3lu6NcGZX2hBrikBZynM/qo9eQWn3VNp50jwF9k70KuforU2flO05KA3bWxw3eUv0kFh/Nw79/UIYKXCZ2BfZQoOd5UWMbtw89Ey8Dv4Ra+Vw5q0LIx9CFxHn56BBYnCCL5v1wAZbKgBDlQfQC0x3ygA1UbXPgGW3d73kYYy11g1/aNsNNVTmf770i9KFRhYvGMNN/B+9S8kQACPIprXl4bpHaDKzVng7ToNu85it7DgNoOXjNrdoc7auyP5mcasCHge3vHQIhOB831+UMqHNdkvuBJed3ZuohO6hAOTgefKMKAsfqoSksGMGS2XekbdeMQUTNezqKQaF7Df5Ks9qD5/wXBV9MHqWUKfcKIxCMXcdYBO7P9TwumTV35ONNMPBgIyRo/YfuGlGSzvEUGYUoG17YD2dXHRVhzGbaCQ6LZqhol9EsAvuONvhyy7s+0tQgoafhw3RDTboMoUFl0IE+iuqcomDk7lnVO0lQcG8/9XaiBho1sY3CQeAysgQ7XCEBcjgbAJ4tj2+cTewpk6fjy4= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DU0PR04MB9417.eurprd04.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230031)(52116005)(366007)(1800799015)(376005)(7416005)(38350700005);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?q?wQan1e6HoRCA9Mi1eXuotBVY9esf?= =?utf-8?q?oQpYQMzAx+rNGvEeKeSvRjAm19ZaHewGpEinKFv0IZHH5BT2Cr9fc2iR7cZsyd1UZ?= =?utf-8?q?h4I6kUGW0N+Uag9lhRGmE7a8FfMoXuSXRJza5eRrpAgrPt5ncPUJ08i6FcuSEMPeE?= =?utf-8?q?P6ChYX+8HNZ2Aqfeo0dds2WP643NFtbLDVuWkxbGM7bWZSoAMpPznzOJVSNzm4NF0?= =?utf-8?q?VpyED8ysSIwpyNFFQhTQSjZEoaASwamQ2XrTRfX6aLM4x2LGDAOIzlx2xFD940Zg7?= =?utf-8?q?JY+U3jewl3e393/YNYjiO2NEQGxmr1SM4tarEnXk8iUuj0GI9HzgNa57KJhRhNAVT?= =?utf-8?q?xcIP2NGXos+zTN/S3yp5Gq9vZmPqQbaOxT9esFQSpli5HBODEra1NHeuCQ6Zui00A?= =?utf-8?q?emgmmYV/62rJJ+uHe2g7K8dIipOvwT/mrRzVqLF9LD2roglQAMGBc4KuyuYV1Hnb4?= =?utf-8?q?odtwtq+JPL9Bqs7ZuBK9hzfsMS0uBKCqZdpxSQyMZ6SSQ67y9V1wM2rCiio1+7cK9?= =?utf-8?q?KCYp/GwWVjvelDtlM03mWiYKIH9i97uau7kUWOynRqdsSZgyN8uhTvuohfuv6seeT?= =?utf-8?q?USXpdrRS01Gu1P5Fq9eRRblyrKRKr92EHTO4lr6shCp5Y2CZ34fnAMVWWC0zYVoLu?= =?utf-8?q?Uk8Xo1VGTIyx7E5+ZDYLm+77WsJSaCGqqtOfCldR2fy6fdu+AUQS2OMnhuMNJLl2s?= =?utf-8?q?FXyZx5j6ndEJVOGjqIvWsQr42H/Uh57oL6kEw3dVNd4x8Z/YANXdWMtuqdgWK4WCB?= =?utf-8?q?ilvtm8MrL2eZ++5U1FMKyYuf8cjlzTytkTZ3sM6ZP3OXHvtgb53BFHn//KWJ+/RCf?= =?utf-8?q?VXBLgsq9xBjRYz6LoazAz1MhkRYkjj0xVfJT2qX928TEe0NGvjvm9ga0iwu+v/KIt?= =?utf-8?q?5RX3Sud+gQ+2berwSw+2mRHMOlLIvdkPz+F2B4wM+oB4teS7mH6yJR9NSfpEib3qe?= =?utf-8?q?+LCC8wRKzKFMqAjURWFFs6gNs7b1cbVX1g934elD89cqfl/j0WSe6yMw/NLffQIwX?= =?utf-8?q?FzDt0yVzUNiFBslMR171qYEc+n/n72vzKUeVBp57BtVTxPKd0tKTYYblnn6iOQg6Y?= =?utf-8?q?n3b9VAr+IrBgwRmJA7ITIVqbjh+kL3NdvXdnd9TUNIKEwYmvnTq4vksuUcqPnYUZa?= =?utf-8?q?mJJzEnJgId5WDybUEscA2v67RJfglji7Yivw2nQ633Nf4ZCUHZV/lSLH+7WWH3pNo?= =?utf-8?q?nE5HFZdb2dv7CWTS8dR7K4zt9c47nDl1t9rPa26BPrBIx9HRTZdIdLaz6QQOIhy29?= =?utf-8?q?d9YiKTC1iq96+ZKoS/DsVmol9rYqK9S7S3dbCPuaYnUTsVxTiFHISbEX/bTcDbhHp?= =?utf-8?q?fF5z87qOdlsDaFSByrHLAwO6lmqnkMxWrtjSJnxQoIhvY7PwXuD0gcVyFVr8LZXfZ?= =?utf-8?q?mG20Kx6LShqpR169KmsNEm/khWSaNjEPNLPMab/0+mf1qFkfo/tI659d4iCC1ZOFK?= =?utf-8?q?RmQDX0rmd7R/vsH5hiNzpKzS/L9iH1RuiXtCW4dt2WhIDDxaFpho7hpw7en8oboRc?= =?utf-8?q?iWV/UMDGLGYF?= X-OriginatorOrg: oss.nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 788082d5-b6c1-4ac7-0827-08dc5f464f40 X-MS-Exchange-CrossTenant-AuthSource: DU0PR04MB9417.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Apr 2024 01:24:36.2573 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: TcHroXCLo7dpV/guGAsreR2hLW1g66iXDLqF1zuHTBj1PqdFxwqONv1KX+dIQdcooNWIre+wgN4i/OD6tMW+4w== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS1PR04MB9264 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240417_182448_945553_C08198B5 X-CRM114-Status: GOOD ( 11.25 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Peng Fan When Agent sending data to SCMI server, the Agent driver could check the size to avoid protocol buffer overflow. So introduce the helper get_max_msg_size. Reviewed-by: Cristian Marussi Reviewed-by: Dhruva Gole Signed-off-by: Peng Fan --- drivers/firmware/arm_scmi/driver.c | 15 +++++++++++++++ drivers/firmware/arm_scmi/protocols.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 36e3eb50a8d4..a1e0e8fa4bb7 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -1537,6 +1537,20 @@ static int scmi_common_extended_name_get(const struct scmi_protocol_handle *ph, return ret; } +/** + * scmi_common_get_max_msg_size - Get maximum message size + * @ph: A protocol handle reference. + * + * Return: Maximum message size for the current protocol. + */ +static int scmi_common_get_max_msg_size(const struct scmi_protocol_handle *ph) +{ + const struct scmi_protocol_instance *pi = ph_to_pi(ph); + struct scmi_info *info = handle_to_scmi_info(pi->handle); + + return info->desc->max_msg_size; +} + /** * struct scmi_iterator - Iterator descriptor * @msg: A reference to the message TX buffer; filled by @prepare_message with @@ -1848,6 +1862,7 @@ static int scmi_protocol_msg_check(const struct scmi_protocol_handle *ph, static const struct scmi_proto_helpers_ops helpers_ops = { .extended_name_get = scmi_common_extended_name_get, + .get_max_msg_size = scmi_common_get_max_msg_size, .iter_response_init = scmi_iterator_init, .iter_response_run = scmi_iterator_run, .protocol_msg_check = scmi_protocol_msg_check, diff --git a/drivers/firmware/arm_scmi/protocols.h b/drivers/firmware/arm_scmi/protocols.h index 317d3fb32676..3e91536a77a3 100644 --- a/drivers/firmware/arm_scmi/protocols.h +++ b/drivers/firmware/arm_scmi/protocols.h @@ -258,6 +258,7 @@ struct scmi_fc_info { * @fastchannel_init: A common helper used to initialize FC descriptors by * gathering FC descriptions from the SCMI platform server. * @fastchannel_db_ring: A common helper to ring a FC doorbell. + * @get_max_msg_size: A common helper to get the maximum message size. */ struct scmi_proto_helpers_ops { int (*extended_name_get)(const struct scmi_protocol_handle *ph, @@ -277,6 +278,7 @@ struct scmi_proto_helpers_ops { struct scmi_fc_db_info **p_db, u32 *rate_limit); void (*fastchannel_db_ring)(struct scmi_fc_db_info *db); + int (*get_max_msg_size)(const struct scmi_protocol_handle *ph); }; /** From patchwork Thu Apr 18 01:32:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Peng Fan (OSS)" X-Patchwork-Id: 13634050 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C5FDBC4345F for ; Thu, 18 Apr 2024 01:25:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Cc:To:In-Reply-To: References:Message-Id:Subject:Date:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=Nd5kC4D913kqr7g7Uf8kXbgSeosLb/cAK9+ndLg3M48=; b=DTtYgnascu/ydZ1QA2Mr3hQun9 OWHhEBjfSjEtw+DWHnDNp+kVYnTOcXFT3z6adyDlfdqgskh6GzNWb2QbrXqLEvYkZ1qjljIi4Yrnr x62kTkjeC9Pk8VvNjnF8auEceCQK7pHbmud0i1YBr/ubYbg7WG6EBjF+/SZxUp6obds4E4A4BJPhl q+U/5ZK6WaOw0KFpkuHrfxPNT3nGYppvvIKyOHaYjp2yGtI1FXFmLmO9i8bG4Kh/PCnihkWgGGSzo PH9tNaE5gYJVjF8YAAc9WnQX69EfUUyOCF+N0M4I51c86M8/pj8h1CYoUAE5603k/VVzQwMowF+Ke 9JY4qbcQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rxGWI-00000000YaQ-2su8; Thu, 18 Apr 2024 01:24:58 +0000 Received: from mail-db8eur05on2062e.outbound.protection.outlook.com ([2a01:111:f400:7e1a::62e] helo=EUR05-DB8-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rxGWA-00000000YTd-2TBh for linux-arm-kernel@lists.infradead.org; Thu, 18 Apr 2024 01:24:52 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=bmx4M6DmYthWkAZTlgkqwiXBzig/AKPzSaxvzt+ItPRoXBr+nBGquQ3LmlddTVKON/4/B18jbg/ZkOsNxPUbi0sumOrN1POe+BEnEEWcYtaYKNaMDUjAUNBuancibyIeWu4heYcCqWeis1NJ01uta3yGiCdl5KJshGa0k9tqMycwUnPD0lEL+gegdgKNerJMC0x5Rf0rv2BVvCicB92TEAKHJFEol0rRJUWjCsCBBjxXOXMxbAEXhU+0QqQiAOt+MevGpkG3cisKcFrheu1QaWhfPXa8xMytxxm+52oKE4/ugiaiAtt6vInfGpqb7uSL+Yqu9nSN4S+U0NX2GKrmCg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=SEk/KyCGYEIR0nJYohvLG9OMHTkixQzPWb3gCR+cLZs=; b=dE6qJoElMWNLsazEnC5CTq2Leqa+lQC8TRiHiDfDg9BF4THRhW8/qx/SXFAM5cg9oTFDNh1XWaR/hQX4IMU3oGpY1rSAtfUsiNnIkr3Ultw6TEE2oJTb2VN/BMaQcQyjU5C+lqwqMDxrDPWdT+SlmjO+D/3fMHRtbX21MgCSXH2BXSyhmHdCWjb4KoIdamgqkzgPWtho0L1xkgpF/hVcpIuwxtaS5/koi7KTDzGw90HL/IUMEucwzRBq8Pp2PAfq6ePSpOYglgGF4TpXv01Cgse/4qJuhpPpP5fVEDVvdNVs8X3xs8P4TEv8eUiCCYXLy99/gAMEUw0SKRXTK3Su3w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oss.nxp.com; dmarc=pass action=none header.from=oss.nxp.com; dkim=pass header.d=oss.nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NXP1.onmicrosoft.com; s=selector2-NXP1-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=SEk/KyCGYEIR0nJYohvLG9OMHTkixQzPWb3gCR+cLZs=; b=kjwTSg5VxcNBkuY36fN5P4WfPaRW0UsTILdt9Qv2zUMU2Cg+AU2fPtB8xy/xSssOUAh5gCCl+QVoSYr7DYQkFAKtpv2ID2pTfHABRkWG48bKRjN3Qee7jQ9IjPLQJgslbXm7ixgxTJIs13Z3bttol018ySbSYTnyfK4J0eQEWp8= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=oss.nxp.com; Received: from DU0PR04MB9417.eurprd04.prod.outlook.com (2603:10a6:10:358::11) by AS1PR04MB9264.eurprd04.prod.outlook.com (2603:10a6:20b:4c4::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7452.50; Thu, 18 Apr 2024 01:24:41 +0000 Received: from DU0PR04MB9417.eurprd04.prod.outlook.com ([fe80::d30b:44e7:e78e:662d]) by DU0PR04MB9417.eurprd04.prod.outlook.com ([fe80::d30b:44e7:e78e:662d%4]) with mapi id 15.20.7452.049; Thu, 18 Apr 2024 01:24:40 +0000 From: "Peng Fan (OSS)" Date: Thu, 18 Apr 2024 09:32:29 +0800 Subject: [PATCH v11 2/4] dt-bindings: firmware: arm,scmi: support pinctrl protocol Message-Id: <20240418-pinctrl-scmi-v11-2-499dca9864a7@nxp.com> References: <20240418-pinctrl-scmi-v11-0-499dca9864a7@nxp.com> In-Reply-To: <20240418-pinctrl-scmi-v11-0-499dca9864a7@nxp.com> To: Sudeep Holla , Cristian Marussi , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Linus Walleij , Dan Carpenter Cc: Dhruva Gole , Andy Shevchenko , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-gpio@vger.kernel.org, Peng Fan X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1713403963; l=2404; i=peng.fan@nxp.com; s=20230812; h=from:subject:message-id; bh=VDmWstcwBhpk6d9BmY1+Svq0j29w4hdHyHMqV4zPF24=; b=AEFUHmUtjgaFBXU1c1XH+FePDq7n6ISgIkzc1WwUltmtdeZNhCpeNJ/whfAiuuNxdZI+SGXWv R8PyapOu6d1CK4vd6UzCpcVKAXMNc0+lwLF+u95R3efsw/rvp7BlzAC X-Developer-Key: i=peng.fan@nxp.com; a=ed25519; pk=I4sJg7atIT1g63H7bb5lDRGR2gJW14RKDD0wFL8TT1g= X-ClientProxiedBy: SG2PR03CA0116.apcprd03.prod.outlook.com (2603:1096:4:91::20) To DU0PR04MB9417.eurprd04.prod.outlook.com (2603:10a6:10:358::11) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DU0PR04MB9417:EE_|AS1PR04MB9264:EE_ X-MS-Office365-Filtering-Correlation-Id: 174c9a6d-00df-4393-907d-08dc5f4651cc X-MS-Exchange-SharedMailbox-RoutingAgent-Processed: True X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: xGKZ4KM9RevLsFhaXgEoA3OjexNonP7J7fVUasU5EouuimIra4ZpSxkvWKfnvgotHbIBcIMg3+RZs+x0C+IhV+KRqUlu6Q/StXFuyCxbqsxpD9IsK10AGr+wATxYFTQ0+AdrnLFsZX0Af7fKv50mOuz5rz2JnjDjGOw48KBbJaPykQ6NSAhcgqehPKm2S0Pxr0qDcrepNy2Vx6pmVA/bQ0sbrsEt0n3gI0EW0IDTjDfnNBwBdJAHL7G5imWs4i3XolTrowB8v0r0eTvJ5qR45DR0rftUyOti7vFJBO104TN2uZvoBEYFhSZe/ewf7wOlAdlRVrGpZrO3E6qe5Wva2huJTynCD/gXErATKBegmEAzyLtF1AsOvSuAva+hUPRsjEpaUiTmLRxlqoJBL/W388oZg2nyUFHacO9Lq9XGdPmPv7ShPFdePJz+EiNpX+yqDVlT/9lG737EL2DHUzUDzPjEKToixn8BdHk9+fRuErE6esvRqfVu/MOKw1fEV7AvH8O015ORmppnOYT/1v5k6lFVUdRyoFXGZeCt31ATyVVxZw1w/erBcxDywE+FbqpjFz0ITUy/FQJclvtvYRLAbtI1F8LHyiCTAXce+G3jUPmCiHKhR9SaPido7DDBwfUel982Od9HK6lvtxBG6HcRFUOTTnbLRpjOMgDlcq2b0msFkPfNIKJut5G0ritoSi56YzE/CWyCq1WwrzNQznxsBaFtcjoMleHauxvsWSzdct4= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DU0PR04MB9417.eurprd04.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230031)(52116005)(366007)(1800799015)(376005)(7416005)(38350700005);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?q?WJ/JcADyGZA3VdCkEu+MkftoBF6E?= =?utf-8?q?LQLZiLUhBRE0dLFmPW18Lcq83JzLcN76kcvJHAIOBPKtsIZokcchGPALPw2B6rvzD?= =?utf-8?q?9ayb+hb0TXTUicTgVCITdVpjN4/hOrRz7tHOx2Eu7bhbbtCrLgUmiRv6Lq4D8tfTl?= =?utf-8?q?bkyXFh/YLsp/TBgUPYWuKxaC6y26Q6955zyid2M9PuCBSxgWp9cJOy2uuTC2me+4r?= =?utf-8?q?x1qt/hz0SRvoq0VdWtpjYNm/IB4XjZlny5whcPNjB6WN05uYkIX4Is4I8ETx/CCHw?= =?utf-8?q?qz6ADDUQ+DaXh0phpaanCI2D+R1+eRhPhsBTtZemN0c63hlnA5EfwApz3A4BHMzvK?= =?utf-8?q?9GHNnMJHkdwhGnsBQbCzOkzd0hGfVn9Wv/0jio4Rkr1cYZoXX9N9umMuQcDzyWb6i?= =?utf-8?q?6K1tsPBHakMtqe2qBriT03FEI/txEWWfTV2X5717YhJlZKnPFPT4RuS7u896K50VL?= =?utf-8?q?++FQyCEZDmaFQD3iRZA7I82yMIrRc7HZGgINZdpUcxt4pCaU/Fh02NPZYLOLQKfMI?= =?utf-8?q?4FpFxf2nGoV+3QzMefIrBA0BVX/RVGyVPes5EwYR224Il8yJYQTewDCDHHWhd+CPV?= =?utf-8?q?/8JP7EeCFnWLzHrm8DuGtFpXmldTujjmCDeDzugDhBz7agV3QLteKcPSryejyYU6z?= =?utf-8?q?6l/3RvmXmqQmaRvsX12CW51xAV+YF0ekFg6E2jdMDKmwwoPTndGyb4ZUMF6SUU1CB?= =?utf-8?q?UllSAjCPWm300i6fVMMCD3ZXJW0PAjkLdCMzt5FMYtIh6XL4ZxbDInv1nP0zW8Hih?= =?utf-8?q?mWPQOXHfnOuXYmUyvYppbpLq0IM0N4L9SIUgIixlAy0xorhq/HY3AyozUT11uB4I/?= =?utf-8?q?K202bu+5exO/VQrSEAlCofzRj3ZEPmAxH2U1378Xkpx0cJfyc5bxJtqiL9KLTayVp?= =?utf-8?q?RVf5I6uGOehhDX72PdinXYWFv8dZZ0YyB06pxqWeMQY+LXEZcTirQW/sUN8FJ/mRZ?= =?utf-8?q?Vss1t0ZluKh633kWYF5RxuoczHUjt6cGb6YAAkzNbpyXHhv3vO35kN6Ll8vhVEAoN?= =?utf-8?q?Ztm9Sxab9KjUKa9LhQ9WgzmyLNBqOuO7CKjXyadVK7axxzz9m2exdYBlph00tMLeD?= =?utf-8?q?y5S+b9oFexHcu8lAKn7zOVg6592uzkx3skP3aKA58huHOR2tVytrUzSvC8SEHw2OF?= =?utf-8?q?FTpmm5tWWrdHNZK4+e/8zpvtCvhGFZl9DouGTThFIFD4q5+L8oBC8/Fr9fn/cVrQ+?= =?utf-8?q?OS4zKSmNHI783xFwihjMuCX4p/ITKlOODIYywj4jFFOc5MtBtcRyrTdasJo4UJ9QV?= =?utf-8?q?nUgy2lEMah2z9XjCJnFjISRXzQyYGD15e2Eyd20tGYhjDxrmF2eEdznYrhexRUqbB?= =?utf-8?q?Bk4I01ldEuUfshXXBM7wPIDD8ildV5lTfc3DzbnWTIMNTtX8M7RrDmJThUfjbgym7?= =?utf-8?q?e5ZKGz38YVSg1pV+NW6H6F9bUfIwcd85F9UvVv7GDta5fX9sctNEcvbyabu9wc1ad?= =?utf-8?q?VkiRuqXut2foL0nJw7RZAwtYos/eKHILVyPQv5kZeGz2088VdKZ1lNg4No8aLPYBT?= =?utf-8?q?zU+POrMgYFCV?= X-OriginatorOrg: oss.nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 174c9a6d-00df-4393-907d-08dc5f4651cc X-MS-Exchange-CrossTenant-AuthSource: DU0PR04MB9417.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Apr 2024 01:24:40.5292 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 9HyyocxzqcSUBMmwP6qyQ/YMXKWX4mUj2gGFua1wyfnJNcwOR45aMmhJrvFQZa+51CRMScXRCDgvWtmaeMugBw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS1PR04MB9264 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240417_182450_712841_61BE4DCD X-CRM114-Status: UNSURE ( 9.47 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Peng Fan Add SCMI v3.2 pinctrl protocol bindings and example. Reviewed-by: Rob Herring Reviewed-by: Linus Walleij Reviewed-by: Dhruva Gole Signed-off-by: Peng Fan --- .../devicetree/bindings/firmware/arm,scmi.yaml | 50 ++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml index 93fb7d05f849..7de2c29606e5 100644 --- a/Documentation/devicetree/bindings/firmware/arm,scmi.yaml +++ b/Documentation/devicetree/bindings/firmware/arm,scmi.yaml @@ -247,6 +247,37 @@ properties: reg: const: 0x18 + protocol@19: + type: object + allOf: + - $ref: '#/$defs/protocol-node' + - $ref: /schemas/pinctrl/pinctrl.yaml + + unevaluatedProperties: false + + properties: + reg: + const: 0x19 + + patternProperties: + '-pins$': + type: object + allOf: + - $ref: /schemas/pinctrl/pincfg-node.yaml# + - $ref: /schemas/pinctrl/pinmux-node.yaml# + unevaluatedProperties: false + + description: + A pin multiplexing sub-node describes how to configure a + set of pins in some desired function. + A single sub-node may define several pin configurations. + This sub-node is using the default pinctrl bindings to configure + pin multiplexing and using SCMI protocol to apply a specified + configuration. + + required: + - reg + additionalProperties: false $defs: @@ -401,6 +432,25 @@ examples: scmi_powercap: protocol@18 { reg = <0x18>; }; + + scmi_pinctrl: protocol@19 { + reg = <0x19>; + + i2c2-pins { + groups = "g_i2c2_a", "g_i2c2_b"; + function = "f_i2c2"; + }; + + mdio-pins { + groups = "g_avb_mdio"; + drive-strength = <24>; + }; + + keys_pins: keys-pins { + pins = "gpio_5_17", "gpio_5_20", "gpio_5_22", "gpio_2_1"; + bias-pull-up; + }; + }; }; }; From patchwork Thu Apr 18 01:32:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Peng Fan (OSS)" X-Patchwork-Id: 13634053 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1B2C6C4345F for ; Thu, 18 Apr 2024 01:25:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Cc:To:In-Reply-To: References:Message-Id:Subject:Date:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=u3672ZLXNO1fr9HL5QerEmuYktuBIs9vyfoRZnjoHYQ=; b=Qb5J6Jd1jt6Pzt2JnYwZUWBwdL nIh6PNFgF2C+vN+lIk8HFMkKbp6v/PY9ijsVS3P1QXAh05PxHqaxtBNaeSciTFdoxI0qpH+3IxUhn 1MaZwdoGgxeTzirt6P3BJZT6tPPHFo5+dVpMk3oB3n+y0geLoxBD8z46+8L8E7amflaWYmH2aoBKt OgR2vruGmnISFvyfhUeOxab43KGkIGUdMEm267SGjBjbjfFKwP8OfGYmX9lYH2qXERAMmMwwrnV5Q QPyqYVMeIlf6469QHIP2RKP7wZByV+43fZRYLtKtXDqg0mOiMCnOcjy3D97EkPNb4WqYZoEqwlGjb ORYj300g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rxGWb-00000000Yku-0Lpz; Thu, 18 Apr 2024 01:25:17 +0000 Received: from mail-db8eur05on2062e.outbound.protection.outlook.com ([2a01:111:f400:7e1a::62e] helo=EUR05-DB8-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rxGWC-00000000YTd-1cBp for linux-arm-kernel@lists.infradead.org; Thu, 18 Apr 2024 01:24:58 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=gaZsEErHVy6dlAdiksPBN1GWFbG9i7iO9ME3gPhkSsB54CWdHHmIYZj+GZSVEBiTJwnkT7AjzDxXtVusHu9EEE6esc4DWosn3byuyoW0qzXQx4JBDzJqssjhPe/iIOXhmTIGUTYlYIvhpE5ijnSmo/wnRbvy1Vc42yKMnvJC+UHCnmNXUSY9llehiREehNTZyl6pN/QQ2+MI7pzDdkHaTOk+0XeJdxS9zIkIKbG1BpeKLayKED552gvRymCcrNRtAVTRnkncy36mGUFQhs8QeFra54S2zytawuS2eikxoYEff1LT7fH/crx9VHt8VszxwXlku53W+SjOmpqG+EacWw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=E6cSrPxrT85E+2sEoi3YYX8D8I3wXNefinoNnLyn7Qk=; b=WXakTQDW/hFtGPucEpO6QQ/SIuPsBe2KBqge78XczmzfUk8m/QX8VFHGAG9Uviz494UQs34IPOXBtUfxmJGFh1h8xYWPrX38wbwU32Hi9wU/f3+uBHy+xiCv90OQsII8a1kLTn/ThE/hUjY8hXXii9JPf4a3bwFiB3nsMepWcPa2Y3YRM6nNzEvsjwQuHgWhYpcjrq6uy3WuYTkJdXLXvm0Zk6+s8BAt4BWkRqNgOdY7eAf7cjV3/l+lRTl57CcGlHcE7+Qb9aC1xSyouQqNH13rTkMgA2CImVdv3o+6UZl3oLlsV+tzv1Lb9VJLOK3w2fSfSJ1W/00XjW5tHt3qPQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oss.nxp.com; dmarc=pass action=none header.from=oss.nxp.com; dkim=pass header.d=oss.nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NXP1.onmicrosoft.com; s=selector2-NXP1-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=E6cSrPxrT85E+2sEoi3YYX8D8I3wXNefinoNnLyn7Qk=; b=i1lpJ0c14fBbTvn2uY4YZZkW7l+ift/ENMSyaFDrYTSUalIb4yCy0g4LTsiGxuRlW32/Pcb29Kc+b41A7Y+1PHj2RyCzYqC63lRqewll/aO5v6CC6dx/vuq6Ldz0ncSuGvSeSSAnpBXg58JlTMNu/T5C6ir9GAfAkMRugEtCRYc= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=oss.nxp.com; Received: from DU0PR04MB9417.eurprd04.prod.outlook.com (2603:10a6:10:358::11) by AS1PR04MB9264.eurprd04.prod.outlook.com (2603:10a6:20b:4c4::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7452.50; Thu, 18 Apr 2024 01:24:45 +0000 Received: from DU0PR04MB9417.eurprd04.prod.outlook.com ([fe80::d30b:44e7:e78e:662d]) by DU0PR04MB9417.eurprd04.prod.outlook.com ([fe80::d30b:44e7:e78e:662d%4]) with mapi id 15.20.7452.049; Thu, 18 Apr 2024 01:24:45 +0000 From: "Peng Fan (OSS)" Date: Thu, 18 Apr 2024 09:32:30 +0800 Subject: [PATCH v11 3/4] firmware: arm_scmi: Add SCMI v3.2 pincontrol protocol basic support Message-Id: <20240418-pinctrl-scmi-v11-3-499dca9864a7@nxp.com> References: <20240418-pinctrl-scmi-v11-0-499dca9864a7@nxp.com> In-Reply-To: <20240418-pinctrl-scmi-v11-0-499dca9864a7@nxp.com> To: Sudeep Holla , Cristian Marussi , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Linus Walleij , Dan Carpenter Cc: Dhruva Gole , Andy Shevchenko , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-gpio@vger.kernel.org, Peng Fan , Oleksii Moisieiev X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1713403963; l=30412; i=peng.fan@nxp.com; s=20230812; h=from:subject:message-id; bh=YuGhTXxfU5NKLJFYyDuKKzadNTpWoQRGvlpy5+5N94w=; b=FrciAiUDPkErcX41ox8q4myXZEJkTRc+DTdHzYBdvly+ZY5PW6k7BqLbrygtT4pYgnveYLI8j av1sGVfrvOnCWyk6KDrQwlYYAzMDmbaXxfyd5B08+C14XnLRJE/Ky4Y X-Developer-Key: i=peng.fan@nxp.com; a=ed25519; pk=I4sJg7atIT1g63H7bb5lDRGR2gJW14RKDD0wFL8TT1g= X-ClientProxiedBy: SG2PR03CA0116.apcprd03.prod.outlook.com (2603:1096:4:91::20) To DU0PR04MB9417.eurprd04.prod.outlook.com (2603:10a6:10:358::11) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DU0PR04MB9417:EE_|AS1PR04MB9264:EE_ X-MS-Office365-Filtering-Correlation-Id: 2bc59104-b935-406b-a735-08dc5f465484 X-MS-Exchange-SharedMailbox-RoutingAgent-Processed: True X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 64aqMbXC+lXgqckFOgnNsL+SkRC9f8aRvgmHsT0VHD0xLU2fblUAT7M5JZPI776N8oNcRt94YPpAZwSsWKgOsfpGsQubFgUpsyUiVt5hAn36l1sIR903wBYh4KwCYK5WqwvYMSwSxuKU8DD5hG+AveoS50aWLHvhdTz+iiRtMrLPzXAE3oHk2TS716yNeYRWljIyC+ZYgVo/pPB5hZImcgvSI+mUqnSRexQbROyZCDxSakPT38rqwssNGfE+cjhJ29Vz2qJSdd6SbTGeWBu/2GN27WbxPP+4NHZEqfKqoqrxJ6P31CjMrpY4/IA8aj2a+kwcxwTPhjhmwJEcUYRo6DsBqZPUYSqa72WL/5O55HWWqzND1eyNdmtOpF5iFL82opTcix5HiV+/vnZ7qVEReoSnck5YgSbTkC78qg7dSH/v3nY63qgSwQfpZson1DJ+NoJaj/fs7Ox6eUHA6HA/m3RDbf9kYIVgtAQHnJ6HcEZhnhAYBqFfb/mDolm0Hz6bBYFuBVHpsft7i/xCC9tYKgnMcOyW5auT4xymfBErOjS1kvy5TRE3unI8sL5ywYj0Gsn5BldjWCT1egJrRlyfgZIvtpXHJASXYo83li3iVs01XtYp4CEZdFYuCwS4jljhD9oy6TUUBjRWIr3mRWp2bjv5t5nvqKj+mJ4egT/7/nGB8dZBenVgFLj1cqne2C5+V/mSRXppmytoxfhzU8JLDkwBy/boVehulbKi+sdqz8A= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DU0PR04MB9417.eurprd04.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230031)(52116005)(366007)(1800799015)(376005)(7416005)(38350700005);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?q?fXgnnAk7wjHkFFEycTQ32ngVRCFw?= =?utf-8?q?b9dJaHlSUIslyIYzL+Tout5tg1wZc2fnQEd6MbjCFrhekXTM2JxMddjcJDyBogktU?= =?utf-8?q?uPxCqYW+YgVkpw9xzKqX5pF3DECuAn6TMoineznNj0ik+JahLx8vdI/OQ54ibyYs5?= =?utf-8?q?OZo5H12Kg2hlCdHbP4TyNHMpS3KVkuDKF3AesvB1Dks+2eZqe8xvdDPnmXtH63qXW?= =?utf-8?q?TANGPCiucUc8fnwyI+RPCc/5Pl2+VGdH/0bU6MMCL4YXMrEOhx9o61gpjht+7XT0I?= =?utf-8?q?d4/vy5mX//MKOlQSJlboWmvEGdNmB084/wEpGVt70zcvE5UL0t5orTnGR+kyY/Pjd?= =?utf-8?q?Q/C+QLZ7gzrFJmrFQyuhnz0B6I6a8VSxQLzRU+VQjqlo1Flzgd0LmcMSg05kEJzDv?= =?utf-8?q?Cq8KnVpYgLPUk6/EN5TubI5qcYIkDj0u14GH7t3hVEGA97rfF5XqoX7cF0wodtfI+?= =?utf-8?q?mvSYcZoAyXWk6rjfCJhcC6oVtE/gL/JaC/uWqJE5MWkhcW/juxWkDDW++nB90VLyb?= =?utf-8?q?WQFzKQADL9YdQ1bVad8YhUtk7soHrn9zzaiHqJA/aEMbpjZ4ZeBMxkxgJEGgwLxTa?= =?utf-8?q?buErBlpfIGYpDokaMmbHUuWDFy1vh0+uHyXF5jer7U5hLw75TYRf00ifzpKyp/xti?= =?utf-8?q?gLgnN9IMAuhniuaKE1BEtoZ/1/pfZ03ydz5rNYWdsfpzJ80XGrA404kAqi8crv4Kj?= =?utf-8?q?miZijsU9ZdkOjcxDlRUR7pgN6IjoWA9oVmq+Uf5xz+NqAzRBcwMmDZjiJr9/OFe5H?= =?utf-8?q?cDqy/EgQXAoHviEDsOB0Fk/z2Bbu7ufLyupEPuDtHCEalY/znVDUH2oH4tRBeNLh9?= =?utf-8?q?S4eGiczuouQeJNc592eI6AuJflrpS79x0PtmgOuf/OvE2H64aqjPnFa5DslVcxM9O?= =?utf-8?q?t3Wk/WfbBcpq42Hd1N83S3TNJYVY+A5P+gHuZBKx4vxlSsx5RcPZZepcR6oYy/K7O?= =?utf-8?q?u9wsLan/fOqvB1wSNenziEmJKj5GvgYwbgAyG9Dadbzl0q365ei7VN8cvPD2c3BkZ?= =?utf-8?q?tzQj3lOb8JvDlrz0TiJpoTCIy9I7KQtJJ9Uh/EzoBDJdvw1NqVYayYYpJeQ+KsTuC?= =?utf-8?q?adrHa4trhxovxLGuCj9f9ylQubSiWKDF9X0VLt23j00G6lb6pJepnNvnQQ/usKNOs?= =?utf-8?q?EFREs0btJyRjXv3op/Nk8BIHjc+w+VJShE54jgk8+Krt1hq8nt1wViK8xDhDKz43w?= =?utf-8?q?oqFtJQs4/wyREmwM2jYEY8S9IMqDlXU+nVO59npNhpvwctr1cTFxRuCU5UbF3KJnx?= =?utf-8?q?BqBA1TKmkEym/Lr7TCvnc1d+hPKg6mVwCCJ9G6dqYMiv3l0PMIA5DwC0w+v0M8YLH?= =?utf-8?q?aHuIO4wNoMj2u3+MM+CBspLj/Qgeix3RnuVrPE+85ZYXBYOKYt/Easi3W/nf1+mtC?= =?utf-8?q?6gCc79pH0mvSdbjO21IP/83GTBpwk7dXaP69pjdsFY/iYOc766NQNQF9q1gylCqwa?= =?utf-8?q?2WO+VFWObmd2YSuTZfu4vbZLzp5KWI57AUBYtl5CxuhBBA0x7IMkzw2vwAAV42w69?= =?utf-8?q?bqQjl1oUfszF?= X-OriginatorOrg: oss.nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 2bc59104-b935-406b-a735-08dc5f465484 X-MS-Exchange-CrossTenant-AuthSource: DU0PR04MB9417.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Apr 2024 01:24:45.1219 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: SHrUmYRIHsUaZFo7XB001vVALcIcto40Wk17+HdgMNPgUWG01QSR2cf1F5pglaKx3Sy/S7YMblC1yZ/3cRd76w== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS1PR04MB9264 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240417_182452_553950_787B6688 X-CRM114-Status: GOOD ( 17.78 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Peng Fan Add basic implementation of the SCMI v3.2 pincontrol protocol. Co-developed-by: Oleksii Moisieiev Signed-off-by: Oleksii Moisieiev Co-developed-by: Cristian Marussi Signed-off-by: Cristian Marussi Signed-off-by: Peng Fan --- drivers/firmware/arm_scmi/Makefile | 3 +- drivers/firmware/arm_scmi/driver.c | 2 + drivers/firmware/arm_scmi/pinctrl.c | 916 ++++++++++++++++++++++++++++++++++ drivers/firmware/arm_scmi/protocols.h | 1 + include/linux/scmi_protocol.h | 84 ++++ 5 files changed, 1005 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/arm_scmi/Makefile b/drivers/firmware/arm_scmi/Makefile index a7bc4796519c..fd59f58ce8a2 100644 --- a/drivers/firmware/arm_scmi/Makefile +++ b/drivers/firmware/arm_scmi/Makefile @@ -10,7 +10,8 @@ scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_SMC) += smc.o scmi-transport-$(CONFIG_ARM_SCMI_HAVE_MSG) += msg.o scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_VIRTIO) += virtio.o scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_OPTEE) += optee.o -scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o voltage.o powercap.o +scmi-protocols-y := base.o clock.o perf.o power.o reset.o sensors.o system.o voltage.o powercap.o +scmi-protocols-y += pinctrl.o scmi-module-objs := $(scmi-driver-y) $(scmi-protocols-y) $(scmi-transport-y) obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-core.o diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index a1e0e8fa4bb7..08ecb918e684 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -3209,6 +3209,7 @@ static int __init scmi_driver_init(void) scmi_voltage_register(); scmi_system_register(); scmi_powercap_register(); + scmi_pinctrl_register(); return platform_driver_register(&scmi_driver); } @@ -3226,6 +3227,7 @@ static void __exit scmi_driver_exit(void) scmi_voltage_unregister(); scmi_system_unregister(); scmi_powercap_unregister(); + scmi_pinctrl_unregister(); scmi_transports_exit(); diff --git a/drivers/firmware/arm_scmi/pinctrl.c b/drivers/firmware/arm_scmi/pinctrl.c new file mode 100644 index 000000000000..a2a7f880d6a3 --- /dev/null +++ b/drivers/firmware/arm_scmi/pinctrl.c @@ -0,0 +1,916 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * System Control and Management Interface (SCMI) Pinctrl Protocol + * + * Copyright (C) 2024 EPAM + * Copyright 2024 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "protocols.h" + +/* Updated only after ALL the mandatory features for that version are merged */ +#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x10000 + +#define GET_GROUPS_NR(x) le32_get_bits((x), GENMASK(31, 16)) +#define GET_PINS_NR(x) le32_get_bits((x), GENMASK(15, 0)) +#define GET_FUNCTIONS_NR(x) le32_get_bits((x), GENMASK(15, 0)) + +#define EXT_NAME_FLAG(x) le32_get_bits((x), BIT(31)) +#define NUM_ELEMS(x) le32_get_bits((x), GENMASK(15, 0)) + +#define REMAINING(x) le32_get_bits((x), GENMASK(31, 16)) +#define RETURNED(x) le32_get_bits((x), GENMASK(11, 0)) + +#define CONFIG_FLAG_MASK GENMASK(19, 18) +#define SELECTOR_MASK GENMASK(17, 16) +#define SKIP_CONFIGS_MASK GENMASK(15, 8) +#define CONFIG_TYPE_MASK GENMASK(7, 0) + +enum scmi_pinctrl_protocol_cmd { + PINCTRL_ATTRIBUTES = 0x3, + PINCTRL_LIST_ASSOCIATIONS = 0x4, + PINCTRL_SETTINGS_GET = 0x5, + PINCTRL_SETTINGS_CONFIGURE = 0x6, + PINCTRL_REQUEST = 0x7, + PINCTRL_RELEASE = 0x8, + PINCTRL_NAME_GET = 0x9, + PINCTRL_SET_PERMISSIONS = 0xa, +}; + +struct scmi_msg_settings_conf { + __le32 identifier; + __le32 function_id; + __le32 attributes; + __le32 configs[]; +}; + +struct scmi_msg_settings_get { + __le32 identifier; + __le32 attributes; +}; + +struct scmi_resp_settings_get { + __le32 function_selected; + __le32 num_configs; + __le32 configs[]; +}; + +struct scmi_msg_pinctrl_protocol_attributes { + __le32 attributes_low; + __le32 attributes_high; +}; + +struct scmi_msg_pinctrl_attributes { + __le32 identifier; + __le32 flags; +}; + +struct scmi_resp_pinctrl_attributes { + __le32 attributes; + u8 name[SCMI_SHORT_NAME_MAX_SIZE]; +}; + +struct scmi_msg_pinctrl_list_assoc { + __le32 identifier; + __le32 flags; + __le32 index; +}; + +struct scmi_resp_pinctrl_list_assoc { + __le32 flags; + __le16 array[]; +}; + +struct scmi_msg_request { + __le32 identifier; + __le32 flags; +}; + +struct scmi_group_info { + char name[SCMI_MAX_STR_SIZE]; + bool present; + u32 *group_pins; + u32 nr_pins; +}; + +struct scmi_function_info { + char name[SCMI_MAX_STR_SIZE]; + bool present; + u32 *groups; + u32 nr_groups; +}; + +struct scmi_pin_info { + char name[SCMI_MAX_STR_SIZE]; + bool present; +}; + +struct scmi_pinctrl_info { + u32 version; + int nr_groups; + int nr_functions; + int nr_pins; + struct scmi_group_info *groups; + struct scmi_function_info *functions; + struct scmi_pin_info *pins; +}; + +static int scmi_pinctrl_attributes_get(const struct scmi_protocol_handle *ph, + struct scmi_pinctrl_info *pi) +{ + int ret; + struct scmi_xfer *t; + struct scmi_msg_pinctrl_protocol_attributes *attr; + + ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 0, sizeof(*attr), &t); + if (ret) + return ret; + + attr = t->rx.buf; + + ret = ph->xops->do_xfer(ph, t); + if (!ret) { + pi->nr_functions = GET_FUNCTIONS_NR(attr->attributes_high); + pi->nr_groups = GET_GROUPS_NR(attr->attributes_low); + pi->nr_pins = GET_PINS_NR(attr->attributes_low); + if (pi->nr_pins == 0) { + dev_warn(ph->dev, "returned zero pins\n"); + ret = -EINVAL; + } + } + + ph->xops->xfer_put(ph, t); + return ret; +} + +static int scmi_pinctrl_count_get(const struct scmi_protocol_handle *ph, + enum scmi_pinctrl_selector_type type) +{ + struct scmi_pinctrl_info *pi = ph->get_priv(ph); + + switch (type) { + case PIN_TYPE: + return pi->nr_pins; + case GROUP_TYPE: + return pi->nr_groups; + case FUNCTION_TYPE: + return pi->nr_functions; + default: + return -EINVAL; + } +} + +static int scmi_pinctrl_validate_id(const struct scmi_protocol_handle *ph, + u32 selector, + enum scmi_pinctrl_selector_type type) +{ + int value; + + value = scmi_pinctrl_count_get(ph, type); + if (value < 0) + return value; + + if (selector >= value || value == 0) + return -EINVAL; + + return 0; +} + +static int scmi_pinctrl_attributes(const struct scmi_protocol_handle *ph, + enum scmi_pinctrl_selector_type type, + u32 selector, char *name, + u32 *n_elems) +{ + int ret; + struct scmi_xfer *t; + struct scmi_msg_pinctrl_attributes *tx; + struct scmi_resp_pinctrl_attributes *rx; + bool ext_name_flag; + + if (!name) + return -EINVAL; + + ret = scmi_pinctrl_validate_id(ph, selector, type); + if (ret) + return ret; + + ret = ph->xops->xfer_get_init(ph, PINCTRL_ATTRIBUTES, sizeof(*tx), + sizeof(*rx), &t); + if (ret) + return ret; + + tx = t->tx.buf; + rx = t->rx.buf; + tx->identifier = cpu_to_le32(selector); + tx->flags = cpu_to_le32(type); + + ret = ph->xops->do_xfer(ph, t); + if (!ret) { + if (n_elems) + *n_elems = NUM_ELEMS(rx->attributes); + + strscpy(name, rx->name, SCMI_SHORT_NAME_MAX_SIZE); + + ext_name_flag = !!EXT_NAME_FLAG(rx->attributes); + } + + ph->xops->xfer_put(ph, t); + + if (ret) + return ret; + /* + * If supported overwrite short name with the extended one; + * on error just carry on and use already provided short name. + */ + if (ext_name_flag) + ret = ph->hops->extended_name_get(ph, PINCTRL_NAME_GET, + selector, (u32 *)&type, name, + SCMI_MAX_STR_SIZE); + return ret; +} + +struct scmi_pinctrl_ipriv { + u32 selector; + enum scmi_pinctrl_selector_type type; + u32 *array; +}; + +static void iter_pinctrl_assoc_prepare_message(void *message, + u32 desc_index, + const void *priv) +{ + struct scmi_msg_pinctrl_list_assoc *msg = message; + const struct scmi_pinctrl_ipriv *p = priv; + + msg->identifier = cpu_to_le32(p->selector); + msg->flags = cpu_to_le32(p->type); + msg->index = cpu_to_le32(desc_index); +} + +static int iter_pinctrl_assoc_update_state(struct scmi_iterator_state *st, + const void *response, void *priv) +{ + const struct scmi_resp_pinctrl_list_assoc *r = response; + + st->num_returned = RETURNED(r->flags); + st->num_remaining = REMAINING(r->flags); + + return 0; +} + +static int +iter_pinctrl_assoc_process_response(const struct scmi_protocol_handle *ph, + const void *response, + struct scmi_iterator_state *st, void *priv) +{ + const struct scmi_resp_pinctrl_list_assoc *r = response; + struct scmi_pinctrl_ipriv *p = priv; + + p->array[st->desc_index + st->loop_idx] = + le16_to_cpu(r->array[st->loop_idx]); + + return 0; +} + +static int scmi_pinctrl_list_associations(const struct scmi_protocol_handle *ph, + u32 selector, + enum scmi_pinctrl_selector_type type, + u16 size, u32 *array) +{ + int ret; + void *iter; + struct scmi_iterator_ops ops = { + .prepare_message = iter_pinctrl_assoc_prepare_message, + .update_state = iter_pinctrl_assoc_update_state, + .process_response = iter_pinctrl_assoc_process_response, + }; + struct scmi_pinctrl_ipriv ipriv = { + .selector = selector, + .type = type, + .array = array, + }; + + if (!array || !size || type == PIN_TYPE) + return -EINVAL; + + ret = scmi_pinctrl_validate_id(ph, selector, type); + if (ret) + return ret; + + iter = ph->hops->iter_response_init(ph, &ops, size, + PINCTRL_LIST_ASSOCIATIONS, + sizeof(struct scmi_msg_pinctrl_list_assoc), + &ipriv); + if (IS_ERR(iter)) + return PTR_ERR(iter); + + return ph->hops->iter_response_run(iter); +} + +struct scmi_settings_get_ipriv { + u32 selector; + enum scmi_pinctrl_selector_type type; + bool get_all; + unsigned int *nr_configs; + enum scmi_pinctrl_conf_type *config_types; + u32 *config_values; +}; + +static void +iter_pinctrl_settings_get_prepare_message(void *message, u32 desc_index, + const void *priv) +{ + struct scmi_msg_settings_get *msg = message; + const struct scmi_settings_get_ipriv *p = priv; + u32 attributes; + + attributes = FIELD_PREP(SELECTOR_MASK, p->type); + + if (p->get_all) { + attributes |= FIELD_PREP(CONFIG_FLAG_MASK, 1) | + FIELD_PREP(SKIP_CONFIGS_MASK, desc_index); + } else { + attributes |= FIELD_PREP(CONFIG_TYPE_MASK, p->config_types[0]); + } + + msg->attributes = cpu_to_le32(attributes); + msg->identifier = cpu_to_le32(p->selector); +} + +static int +iter_pinctrl_settings_get_update_state(struct scmi_iterator_state *st, + const void *response, void *priv) +{ + const struct scmi_resp_settings_get *r = response; + struct scmi_settings_get_ipriv *p = priv; + + if (p->get_all) { + st->num_returned = le32_get_bits(r->num_configs, GENMASK(7, 0)); + st->num_remaining = le32_get_bits(r->num_configs, GENMASK(31, 24)); + } else { + st->num_returned = 1; + st->num_remaining = 0; + } + + return 0; +} + +static int +iter_pinctrl_settings_get_process_response(const struct scmi_protocol_handle *ph, + const void *response, + struct scmi_iterator_state *st, + void *priv) +{ + const struct scmi_resp_settings_get *r = response; + struct scmi_settings_get_ipriv *p = priv; + u32 type = le32_get_bits(r->configs[st->loop_idx * 2], GENMASK(7, 0)); + u32 val = le32_to_cpu(r->configs[st->loop_idx * 2 + 1]); + + if (p->get_all) { + p->config_types[st->desc_index + st->loop_idx] = type; + } else { + if (p->config_types[0] != type) + return -EINVAL; + } + + p->config_values[st->desc_index + st->loop_idx] = val; + ++*p->nr_configs; + + return 0; +} + +static int +scmi_pinctrl_settings_get(const struct scmi_protocol_handle *ph, u32 selector, + enum scmi_pinctrl_selector_type type, + unsigned int *nr_configs, + enum scmi_pinctrl_conf_type *config_types, + u32 *config_values) +{ + int ret; + void *iter; + unsigned int max_configs = *nr_configs; + struct scmi_iterator_ops ops = { + .prepare_message = iter_pinctrl_settings_get_prepare_message, + .update_state = iter_pinctrl_settings_get_update_state, + .process_response = iter_pinctrl_settings_get_process_response, + }; + struct scmi_settings_get_ipriv ipriv = { + .selector = selector, + .type = type, + .get_all = (max_configs > 1), + .nr_configs = nr_configs, + .config_types = config_types, + .config_values = config_values, + }; + + if (!config_types || !config_values || type == FUNCTION_TYPE) + return -EINVAL; + + ret = scmi_pinctrl_validate_id(ph, selector, type); + if (ret) + return ret; + + /* Prepare to count returned configs */ + *nr_configs = 0; + iter = ph->hops->iter_response_init(ph, &ops, max_configs, + PINCTRL_SETTINGS_GET, + sizeof(struct scmi_msg_settings_get), + &ipriv); + if (IS_ERR(iter)) + return PTR_ERR(iter); + + return ph->hops->iter_response_run(iter); +} + +static int scmi_pinctrl_settings_get_one(const struct scmi_protocol_handle *ph, + u32 selector, + enum scmi_pinctrl_selector_type type, + enum scmi_pinctrl_conf_type config_type, + u32 *config_value) +{ + unsigned int nr_configs = 1; + + return scmi_pinctrl_settings_get(ph, selector, type, &nr_configs, + &config_type, config_value); +} + +static int scmi_pinctrl_settings_get_all(const struct scmi_protocol_handle *ph, + u32 selector, + enum scmi_pinctrl_selector_type type, + unsigned int *nr_configs, + enum scmi_pinctrl_conf_type *config_types, + u32 *config_values) +{ + if (!nr_configs || *nr_configs == 0) + return -EINVAL; + + return scmi_pinctrl_settings_get(ph, selector, type, nr_configs, + config_types, config_values); +} + +static int +scmi_pinctrl_settings_conf(const struct scmi_protocol_handle *ph, + u32 selector, + enum scmi_pinctrl_selector_type type, + u32 nr_configs, + enum scmi_pinctrl_conf_type *config_type, + u32 *config_value) +{ + struct scmi_xfer *t; + struct scmi_msg_settings_conf *tx; + u32 attributes; + int ret, i; + u32 configs_in_chunk, conf_num = 0; + u32 chunk; + int max_msg_size = ph->hops->get_max_msg_size(ph); + + if (!config_type || !config_value || type == FUNCTION_TYPE) + return -EINVAL; + + ret = scmi_pinctrl_validate_id(ph, selector, type); + if (ret) + return ret; + + configs_in_chunk = (max_msg_size - sizeof(*tx)) / (sizeof(__le32) * 2); + while (conf_num < nr_configs) { + chunk = (nr_configs - conf_num > configs_in_chunk) ? + configs_in_chunk : nr_configs - conf_num; + + ret = ph->xops->xfer_get_init(ph, PINCTRL_SETTINGS_CONFIGURE, + sizeof(*tx) + + chunk * 2 * sizeof(__le32), 0, &t); + if (ret) + break; + + tx = t->tx.buf; + tx->identifier = cpu_to_le32(selector); + tx->function_id = cpu_to_le32(0xFFFFFFFF); + attributes = FIELD_PREP(GENMASK(1, 0), type) | + FIELD_PREP(GENMASK(9, 2), chunk); + tx->attributes = cpu_to_le32(attributes); + + for (i = 0; i < chunk; i++) { + tx->configs[i * 2] = + cpu_to_le32(config_type[conf_num + i]); + tx->configs[i * 2 + 1] = + cpu_to_le32(config_value[conf_num + i]); + } + + ret = ph->xops->do_xfer(ph, t); + + ph->xops->xfer_put(ph, t); + + if (ret) + break; + + conf_num += chunk; + } + + return ret; +} + +static int scmi_pinctrl_function_select(const struct scmi_protocol_handle *ph, + u32 group, + enum scmi_pinctrl_selector_type type, + u32 function_id) +{ + int ret; + struct scmi_xfer *t; + struct scmi_msg_settings_conf *tx; + u32 attributes; + + ret = scmi_pinctrl_validate_id(ph, group, type); + if (ret) + return ret; + + ret = ph->xops->xfer_get_init(ph, PINCTRL_SETTINGS_CONFIGURE, + sizeof(*tx), 0, &t); + if (ret) + return ret; + + tx = t->tx.buf; + tx->identifier = cpu_to_le32(group); + tx->function_id = cpu_to_le32(function_id); + attributes = FIELD_PREP(GENMASK(1, 0), type) | BIT(10); + tx->attributes = cpu_to_le32(attributes); + + ret = ph->xops->do_xfer(ph, t); + ph->xops->xfer_put(ph, t); + + return ret; +} + +static int scmi_pinctrl_request_free(const struct scmi_protocol_handle *ph, + u32 identifier, + enum scmi_pinctrl_selector_type type, + enum scmi_pinctrl_protocol_cmd cmd) +{ + int ret; + struct scmi_xfer *t; + struct scmi_msg_request *tx; + + if (type == FUNCTION_TYPE) + return -EINVAL; + + if (cmd != PINCTRL_REQUEST && cmd != PINCTRL_RELEASE) + return -EINVAL; + + ret = scmi_pinctrl_validate_id(ph, identifier, type); + if (ret) + return ret; + + ret = ph->xops->xfer_get_init(ph, cmd, sizeof(*tx), 0, &t); + if (ret) + return ret; + + tx = t->tx.buf; + tx->identifier = cpu_to_le32(identifier); + tx->flags = cpu_to_le32(type); + + ret = ph->xops->do_xfer(ph, t); + ph->xops->xfer_put(ph, t); + + return ret; +} + +static int scmi_pinctrl_pin_request(const struct scmi_protocol_handle *ph, + u32 pin) +{ + return scmi_pinctrl_request_free(ph, pin, PIN_TYPE, PINCTRL_REQUEST); +} + +static int scmi_pinctrl_pin_free(const struct scmi_protocol_handle *ph, u32 pin) +{ + return scmi_pinctrl_request_free(ph, pin, PIN_TYPE, PINCTRL_RELEASE); +} + +static int scmi_pinctrl_get_group_info(const struct scmi_protocol_handle *ph, + u32 selector, + struct scmi_group_info *group) +{ + int ret; + + ret = scmi_pinctrl_attributes(ph, GROUP_TYPE, selector, group->name, + &group->nr_pins); + if (ret) + return ret; + + if (!group->nr_pins) { + dev_err(ph->dev, "Group %d has 0 elements", selector); + return -ENODATA; + } + + group->group_pins = kmalloc_array(group->nr_pins, + sizeof(*group->group_pins), + GFP_KERNEL); + if (!group->group_pins) + return -ENOMEM; + + ret = scmi_pinctrl_list_associations(ph, selector, GROUP_TYPE, + group->nr_pins, group->group_pins); + if (ret) { + kfree(group->group_pins); + return ret; + } + + group->present = true; + return 0; +} + +static int scmi_pinctrl_get_group_name(const struct scmi_protocol_handle *ph, + u32 selector, const char **name) +{ + struct scmi_pinctrl_info *pi = ph->get_priv(ph); + + if (!name) + return -EINVAL; + + if (selector >= pi->nr_groups || pi->nr_groups == 0) + return -EINVAL; + + if (!pi->groups[selector].present) { + int ret; + + ret = scmi_pinctrl_get_group_info(ph, selector, + &pi->groups[selector]); + if (ret) + return ret; + } + + *name = pi->groups[selector].name; + + return 0; +} + +static int scmi_pinctrl_group_pins_get(const struct scmi_protocol_handle *ph, + u32 selector, const u32 **pins, + u32 *nr_pins) +{ + struct scmi_pinctrl_info *pi = ph->get_priv(ph); + + if (!pins || !nr_pins) + return -EINVAL; + + if (selector >= pi->nr_groups || pi->nr_groups == 0) + return -EINVAL; + + if (!pi->groups[selector].present) { + int ret; + + ret = scmi_pinctrl_get_group_info(ph, selector, + &pi->groups[selector]); + if (ret) + return ret; + } + + *pins = pi->groups[selector].group_pins; + *nr_pins = pi->groups[selector].nr_pins; + + return 0; +} + +static int scmi_pinctrl_get_function_info(const struct scmi_protocol_handle *ph, + u32 selector, + struct scmi_function_info *func) +{ + int ret; + + ret = scmi_pinctrl_attributes(ph, FUNCTION_TYPE, selector, func->name, + &func->nr_groups); + if (ret) + return ret; + + if (!func->nr_groups) { + dev_err(ph->dev, "Function %d has 0 elements", selector); + return -ENODATA; + } + + func->groups = kmalloc_array(func->nr_groups, sizeof(*func->groups), + GFP_KERNEL); + if (!func->groups) + return -ENOMEM; + + ret = scmi_pinctrl_list_associations(ph, selector, FUNCTION_TYPE, + func->nr_groups, func->groups); + if (ret) { + kfree(func->groups); + return ret; + } + + func->present = true; + return 0; +} + +static int scmi_pinctrl_get_function_name(const struct scmi_protocol_handle *ph, + u32 selector, const char **name) +{ + struct scmi_pinctrl_info *pi = ph->get_priv(ph); + + if (!name) + return -EINVAL; + + if (selector >= pi->nr_functions || pi->nr_functions == 0) + return -EINVAL; + + if (!pi->functions[selector].present) { + int ret; + + ret = scmi_pinctrl_get_function_info(ph, selector, + &pi->functions[selector]); + if (ret) + return ret; + } + + *name = pi->functions[selector].name; + return 0; +} + +static int +scmi_pinctrl_function_groups_get(const struct scmi_protocol_handle *ph, + u32 selector, u32 *nr_groups, + const u32 **groups) +{ + struct scmi_pinctrl_info *pi = ph->get_priv(ph); + + if (!groups || !nr_groups) + return -EINVAL; + + if (selector >= pi->nr_functions || pi->nr_functions == 0) + return -EINVAL; + + if (!pi->functions[selector].present) { + int ret; + + ret = scmi_pinctrl_get_function_info(ph, selector, + &pi->functions[selector]); + if (ret) + return ret; + } + + *groups = pi->functions[selector].groups; + *nr_groups = pi->functions[selector].nr_groups; + + return 0; +} + +static int scmi_pinctrl_mux_set(const struct scmi_protocol_handle *ph, + u32 selector, u32 group) +{ + return scmi_pinctrl_function_select(ph, group, GROUP_TYPE, selector); +} + +static int scmi_pinctrl_get_pin_info(const struct scmi_protocol_handle *ph, + u32 selector, struct scmi_pin_info *pin) +{ + int ret; + + if (!pin) + return -EINVAL; + + ret = scmi_pinctrl_attributes(ph, PIN_TYPE, selector, pin->name, NULL); + if (ret) + return ret; + + pin->present = true; + return 0; +} + +static int scmi_pinctrl_get_pin_name(const struct scmi_protocol_handle *ph, + u32 selector, const char **name) +{ + struct scmi_pinctrl_info *pi = ph->get_priv(ph); + + if (!name) + return -EINVAL; + + if (selector >= pi->nr_pins) + return -EINVAL; + + if (!pi->pins[selector].present) { + int ret; + + ret = scmi_pinctrl_get_pin_info(ph, selector, &pi->pins[selector]); + if (ret) + return ret; + } + + *name = pi->pins[selector].name; + + return 0; +} + +static int scmi_pinctrl_name_get(const struct scmi_protocol_handle *ph, + u32 selector, + enum scmi_pinctrl_selector_type type, + const char **name) +{ + switch (type) { + case PIN_TYPE: + return scmi_pinctrl_get_pin_name(ph, selector, name); + case GROUP_TYPE: + return scmi_pinctrl_get_group_name(ph, selector, name); + case FUNCTION_TYPE: + return scmi_pinctrl_get_function_name(ph, selector, name); + default: + return -EINVAL; + } +} + +static const struct scmi_pinctrl_proto_ops pinctrl_proto_ops = { + .count_get = scmi_pinctrl_count_get, + .name_get = scmi_pinctrl_name_get, + .group_pins_get = scmi_pinctrl_group_pins_get, + .function_groups_get = scmi_pinctrl_function_groups_get, + .mux_set = scmi_pinctrl_mux_set, + .settings_get_one = scmi_pinctrl_settings_get_one, + .settings_get_all = scmi_pinctrl_settings_get_all, + .settings_conf = scmi_pinctrl_settings_conf, + .pin_request = scmi_pinctrl_pin_request, + .pin_free = scmi_pinctrl_pin_free, +}; + +static int scmi_pinctrl_protocol_init(const struct scmi_protocol_handle *ph) +{ + int ret; + u32 version; + struct scmi_pinctrl_info *pinfo; + + ret = ph->xops->version_get(ph, &version); + if (ret) + return ret; + + dev_dbg(ph->dev, "Pinctrl Version %d.%d\n", + PROTOCOL_REV_MAJOR(version), PROTOCOL_REV_MINOR(version)); + + pinfo = devm_kzalloc(ph->dev, sizeof(*pinfo), GFP_KERNEL); + if (!pinfo) + return -ENOMEM; + + ret = scmi_pinctrl_attributes_get(ph, pinfo); + if (ret) + return ret; + + pinfo->pins = devm_kcalloc(ph->dev, pinfo->nr_pins, + sizeof(*pinfo->pins), GFP_KERNEL); + if (!pinfo->pins) + return -ENOMEM; + + pinfo->groups = devm_kcalloc(ph->dev, pinfo->nr_groups, + sizeof(*pinfo->groups), GFP_KERNEL); + if (!pinfo->groups) + return -ENOMEM; + + pinfo->functions = devm_kcalloc(ph->dev, pinfo->nr_functions, + sizeof(*pinfo->functions), GFP_KERNEL); + if (!pinfo->functions) + return -ENOMEM; + + pinfo->version = version; + + return ph->set_priv(ph, pinfo, version); +} + +static int scmi_pinctrl_protocol_deinit(const struct scmi_protocol_handle *ph) +{ + int i; + struct scmi_pinctrl_info *pi = ph->get_priv(ph); + + /* Free groups_pins allocated in scmi_pinctrl_get_group_info */ + for (i = 0; i < pi->nr_groups; i++) { + if (pi->groups[i].present) { + kfree(pi->groups[i].group_pins); + pi->groups[i].present = false; + } + } + + /* Free groups allocated in scmi_pinctrl_get_function_info */ + for (i = 0; i < pi->nr_functions; i++) { + if (pi->functions[i].present) { + kfree(pi->functions[i].groups); + pi->functions[i].present = false; + } + } + + return 0; +} + +static const struct scmi_protocol scmi_pinctrl = { + .id = SCMI_PROTOCOL_PINCTRL, + .owner = THIS_MODULE, + .instance_init = &scmi_pinctrl_protocol_init, + .instance_deinit = &scmi_pinctrl_protocol_deinit, + .ops = &pinctrl_proto_ops, + .supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION, +}; +DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(pinctrl, scmi_pinctrl) diff --git a/drivers/firmware/arm_scmi/protocols.h b/drivers/firmware/arm_scmi/protocols.h index 3e91536a77a3..c02cbfd2bb03 100644 --- a/drivers/firmware/arm_scmi/protocols.h +++ b/drivers/firmware/arm_scmi/protocols.h @@ -355,6 +355,7 @@ void __exit scmi_##name##_unregister(void) \ DECLARE_SCMI_REGISTER_UNREGISTER(base); DECLARE_SCMI_REGISTER_UNREGISTER(clock); DECLARE_SCMI_REGISTER_UNREGISTER(perf); +DECLARE_SCMI_REGISTER_UNREGISTER(pinctrl); DECLARE_SCMI_REGISTER_UNREGISTER(power); DECLARE_SCMI_REGISTER_UNREGISTER(reset); DECLARE_SCMI_REGISTER_UNREGISTER(sensors); diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h index a3addb07e00a..3a9bb5b9a9e8 100644 --- a/include/linux/scmi_protocol.h +++ b/include/linux/scmi_protocol.h @@ -737,6 +737,89 @@ struct scmi_powercap_proto_ops { u32 *power_thresh_high); }; +enum scmi_pinctrl_selector_type { + PIN_TYPE = 0, + GROUP_TYPE, + FUNCTION_TYPE, +}; + +enum scmi_pinctrl_conf_type { + SCMI_PIN_DEFAULT = 0, + SCMI_PIN_BIAS_BUS_HOLD = 1, + SCMI_PIN_BIAS_DISABLE = 2, + SCMI_PIN_BIAS_HIGH_IMPEDANCE = 3, + SCMI_PIN_BIAS_PULL_UP = 4, + SCMI_PIN_BIAS_PULL_DEFAULT = 5, + SCMI_PIN_BIAS_PULL_DOWN = 6, + SCMI_PIN_DRIVE_OPEN_DRAIN = 7, + SCMI_PIN_DRIVE_OPEN_SOURCE = 8, + SCMI_PIN_DRIVE_PUSH_PULL = 9, + SCMI_PIN_DRIVE_STRENGTH = 10, + SCMI_PIN_INPUT_DEBOUNCE = 11, + SCMI_PIN_INPUT_MODE = 12, + SCMI_PIN_PULL_MODE = 13, + SCMI_PIN_INPUT_VALUE = 14, + SCMI_PIN_INPUT_SCHMITT = 15, + SCMI_PIN_LOW_POWER_MODE = 16, + SCMI_PIN_OUTPUT_MODE = 17, + SCMI_PIN_OUTPUT_VALUE = 18, + SCMI_PIN_POWER_SOURCE = 19, + SCMI_PIN_SLEW_RATE = 20, + SCMI_PIN_OEM_START = 192, + SCMI_PIN_OEM_END = 255, +}; + +/** + * struct scmi_pinctrl_proto_ops - represents the various operations provided + * by SCMI Pinctrl Protocol + * + * @count_get: returns count of the registered elements in given type + * @name_get: returns name by index of given type + * @group_pins_get: returns the set of pins, assigned to the specified group + * @function_groups_get: returns the set of groups, assigned to the specified + * function + * @mux_set: set muxing function for groups of pins + * @settings_get_one: returns one configuration parameter for pin or group + * specified by config_type + * @settings_get_all: returns all configuration parameters for pin or group + * @settings_conf: sets the configuration parameter for pin or group + * @pin_request: aquire pin before selecting mux setting + * @pin_free: frees pin, acquired by request_pin call + */ +struct scmi_pinctrl_proto_ops { + int (*count_get)(const struct scmi_protocol_handle *ph, + enum scmi_pinctrl_selector_type type); + int (*name_get)(const struct scmi_protocol_handle *ph, u32 selector, + enum scmi_pinctrl_selector_type type, + const char **name); + int (*group_pins_get)(const struct scmi_protocol_handle *ph, + u32 selector, const unsigned int **pins, + unsigned int *nr_pins); + int (*function_groups_get)(const struct scmi_protocol_handle *ph, + u32 selector, unsigned int *nr_groups, + const unsigned int **groups); + int (*mux_set)(const struct scmi_protocol_handle *ph, u32 selector, + u32 group); + int (*settings_get_one)(const struct scmi_protocol_handle *ph, + u32 selector, + enum scmi_pinctrl_selector_type type, + enum scmi_pinctrl_conf_type config_type, + u32 *config_value); + int (*settings_get_all)(const struct scmi_protocol_handle *ph, + u32 selector, + enum scmi_pinctrl_selector_type type, + unsigned int *nr_configs, + enum scmi_pinctrl_conf_type *config_types, + u32 *config_values); + int (*settings_conf)(const struct scmi_protocol_handle *ph, + u32 selector, enum scmi_pinctrl_selector_type type, + unsigned int nr_configs, + enum scmi_pinctrl_conf_type *config_type, + u32 *config_value); + int (*pin_request)(const struct scmi_protocol_handle *ph, u32 pin); + int (*pin_free)(const struct scmi_protocol_handle *ph, u32 pin); +}; + /** * struct scmi_notify_ops - represents notifications' operations provided by * SCMI core @@ -842,6 +925,7 @@ enum scmi_std_protocol { SCMI_PROTOCOL_RESET = 0x16, SCMI_PROTOCOL_VOLTAGE = 0x17, SCMI_PROTOCOL_POWERCAP = 0x18, + SCMI_PROTOCOL_PINCTRL = 0x19, }; enum scmi_system_events { From patchwork Thu Apr 18 01:32:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Peng Fan (OSS)" X-Patchwork-Id: 13634052 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 63A7BC4345F for ; Thu, 18 Apr 2024 01:25:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Cc:To:In-Reply-To: References:Message-Id:Subject:Date:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=tudFf+vWgQgBYUjOA73EC3udwhtfS0RfJ7TxC9VtQu0=; b=C+nqY8/WGZNXULOoR0APJM5JpV 3DvNY2C3UwLOuPzpFs1Vz+6vpjPxmhvR/w2f1GAkgbVH71YFVLArKTwf2QFGNH1A3DoEhny8/+h7V nWi6dQ9cRKTk80LxKiHmrcW+t/8S9gXEMf4HfvFxLn3DdhVFUTvjY0N8Vgs/vYloodlQ92DEmjCfu tSZMAedU1mPYHmluuSmGlUqALp1gPyX5o6WSxYvyXBn1RArTA+mEO3FaBGX5Flo8GlRNshliC8eu7 bMft5k2rh/W9IJmDlUfzsY4MBNgHwe+K6RLlwkxG2MW2KHXrYW2BMjNcEyQNG1Tw7ek3UxhLGVSNs gv5QD3qg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rxGWc-00000000Ylz-2DTn; Thu, 18 Apr 2024 01:25:18 +0000 Received: from mail-am0eur02on20600.outbound.protection.outlook.com ([2a01:111:f403:2606::600] helo=EUR02-AM0-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rxGWH-00000000YYY-1wAT for linux-arm-kernel@lists.infradead.org; Thu, 18 Apr 2024 01:24:59 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=TwBQ8xdcIqtgLfVipuFUISbOFRNue5MydRnp28ak92h4py0oFoYa2ztc7U/mTKgxS5LpfF5SkMYQ3kPt4Vsbp1huG+5YHY0HT6Bm/X+LRHRoPiH6/StU6nYXDCjIEDAHvOVoKcD0aJG44R9TiEI4C1bnZy7yVLW2XLEEbxFS/F4J0JGV7dqZFRAEqLoMo725eOBCe2dvo/PfH+SHRRJIKPOc6qnRt6V1Wfj++d8Ph2B1lmZA0ObmwiQLnQxoxOr7awCwhXJsHZSjynj8apWYhisewyIftsXbNCsqZVwJbJTAAxYwF7Qf49L6iffLTuKjNw63aJsWAmbGTWhgxUkcZQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=HdTqCJnUPXMf0EXaB/2Sjjabw4CHiCSwDMNNHya1rMM=; b=Bm6b9lwBUe2bfe3ynm8kbn5fhI1Q+G2T40OkwDBHh0I/ViTtVI68Rhj4FjrmGbxBMvU7HDwracYVO59OXydphX2ejirQL4RTQzuIWp4/j2zmb+PesHdM2jufoGhqINNqAQ/xK4zA2nFxO1RBZUg4xlAJPJ27Hrgwd4H+iLdBQ8ltyWO3IggLnxqzY0kGGdB3syY3ocMbImNPbJDRJFJJuQkHQge8hc/XyirE68h4bdpTzqYbcKyMukz+hvqyenxhk5JU7pBDXsh2gYIyPRgLLJTZMuqWXSF5K4hoVzwM8bj0vCk4nKgRVEa9phoYB5klqhY9kVV7AZbBcJ5Nlyt0rQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oss.nxp.com; dmarc=pass action=none header.from=oss.nxp.com; dkim=pass header.d=oss.nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NXP1.onmicrosoft.com; s=selector2-NXP1-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=HdTqCJnUPXMf0EXaB/2Sjjabw4CHiCSwDMNNHya1rMM=; b=Vz9E2+yHPcST3Mt66JkU59ahCrpq6FAHut7x+DVP6adGgE3vdC8wwIoisv2YpRvASY4Bf/TWSKIeM5at6yxEmIVFfMZM26EZK4mEpLkOc+eiKreBHSgdZfu7Qvil+pI1RV35UdFzWdN6nc44n0IUPuHrkBzmpnoBXpzjEEuGqRw= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=oss.nxp.com; Received: from DU0PR04MB9417.eurprd04.prod.outlook.com (2603:10a6:10:358::11) by AM7PR04MB7110.eurprd04.prod.outlook.com (2603:10a6:20b:119::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7452.50; Thu, 18 Apr 2024 01:24:50 +0000 Received: from DU0PR04MB9417.eurprd04.prod.outlook.com ([fe80::d30b:44e7:e78e:662d]) by DU0PR04MB9417.eurprd04.prod.outlook.com ([fe80::d30b:44e7:e78e:662d%4]) with mapi id 15.20.7452.049; Thu, 18 Apr 2024 01:24:49 +0000 From: "Peng Fan (OSS)" Date: Thu, 18 Apr 2024 09:32:31 +0800 Subject: [PATCH v11 4/4] pinctrl: Implementation of the generic scmi-pinctrl driver Message-Id: <20240418-pinctrl-scmi-v11-4-499dca9864a7@nxp.com> References: <20240418-pinctrl-scmi-v11-0-499dca9864a7@nxp.com> In-Reply-To: <20240418-pinctrl-scmi-v11-0-499dca9864a7@nxp.com> To: Sudeep Holla , Cristian Marussi , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Linus Walleij , Dan Carpenter Cc: Dhruva Gole , Andy Shevchenko , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-gpio@vger.kernel.org, Peng Fan , Oleksii Moisieiev , Andy Shevchenko X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1713403963; l=18594; i=peng.fan@nxp.com; s=20230812; h=from:subject:message-id; bh=frIY1kOz5TJs/gHZBgAO0T8Kpa1lYIWOgEfr1Im7os4=; b=Z8jFpGvLlmPyD6/nOljzUOW9IO3U3UWKuF/auwzSVqvwmTLHH08OzIoCt2X7qeLXY9GAOSvqp mK4RcXvnUoaCk9NdLVEH9EjMgvSBmqIE+c3c0DNY4AnQvNe/mvi6Tpu X-Developer-Key: i=peng.fan@nxp.com; a=ed25519; pk=I4sJg7atIT1g63H7bb5lDRGR2gJW14RKDD0wFL8TT1g= X-ClientProxiedBy: SG2PR03CA0116.apcprd03.prod.outlook.com (2603:1096:4:91::20) To DU0PR04MB9417.eurprd04.prod.outlook.com (2603:10a6:10:358::11) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DU0PR04MB9417:EE_|AM7PR04MB7110:EE_ X-MS-Office365-Filtering-Correlation-Id: 21c97aac-3bd3-484e-4035-08dc5f46575d X-MS-Exchange-SharedMailbox-RoutingAgent-Processed: True X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: azjz329YfckjZShlmN85hvzziDW6PmMaUV2EDgdRKoh2jddFdBuWQ/LlAkXWvtdGUeSZ63LD1RMLDRvp9ZPqSllUpESFn7HEbnyRvCakxp6CXlG9T3HQc+HxGfG8mPvSO2j5qfFNuzca1WpMrKlmTpRWzfA9dkzKtCM9alofu5IacPcWMd+cpY6GCl7JIdDTLwvIJtUgTt3jqKFt1odl9XMoZRw22FXmHW0CO9fpgQCNetUCrOR8T0Mg9ZicisgTei4W8igUYnDa/WgrdgU0csrJZQWjpbmVI75OzVJM0z3Ejk+qQFLFCz6olHxjiv7SZvAgv61OfTHvAcqDgdbhCS84NK+NojSan/BmQW9ZVTIYBnXYoDWAjQds5HaBUUf3tY5i5HgXQ9CiyxZ7cyw3UeKKsWChByX3OunatMxLA3muFiFQv1yqjjFEsUkrxtDFCNVuzBGKCoVrSxzPW52mEX0Thx3aOYo7ZzCZ074VqK1KX9EgIqqob0cIlqHGkKRUn3OY6f+wm/mzb5EcuF9tZC9SCmUvYB8oY5KvOso9HrBche/tOEzodu46dLdE723hhklfzBhYABDSqZ+TL4WAdLrDsqHVuXGYrNuOaq6OYwx/otVFcbvNR/trqwaDAB3cn7pyKC5E9mL5e6XQnHyWI9VdTn3Dw6L54THruEtwNlkiywfGl0yE2Fb7wbU5mFsQQH5QXqsX7aLXzAAR4VuPq1tafroVElp7DasH526HrTU= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DU0PR04MB9417.eurprd04.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230031)(52116005)(366007)(1800799015)(7416005)(376005)(38350700005);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?q?7kQvqUonHTkWKVpi+YKSPSnVYdGI?= =?utf-8?q?BVi/cibIdqWMA/VhNfTx8scQ0KIbMIBSrQHGYsIcZh8QWzxxHinzqy2WQLd9EaPA9?= =?utf-8?q?mwfGxkioNwlomDTiIzKSkqnuO2NSWq4uDL3rPuxU+hR1G6UDT2g4+tazjjXuaSB9j?= =?utf-8?q?yyHSKVoPWADdnbe/8jIGFamkOJSwRN60a9ko4aMDwvVEwASa2akkqAH8Ahhff3zGG?= =?utf-8?q?2Ni8hkYaOR8jY+wRaIqhJD+AOiif4O7qRh7Fyf38MDKa+m1b40F+UkKntoF725s0z?= =?utf-8?q?15ZTVqRISYRc9jhqqd9c/0862N8Fil2mKxAPYqnPXhNK45fPRs3VUBCCcdWIiAxOB?= =?utf-8?q?Un7uwPCCDa5QW7XlSTtW4IjYdXJ4S2bjt8+fsAFctJCAFFw1Asb6U4A/0dGwrzKmX?= =?utf-8?q?sHDXh4/reK35oqeVUF6TwUmb73i7CrqvL6YARniFqr97x6wL1fYyG/fs4tA5NVlV3?= =?utf-8?q?+kbzhK75TsHDEqkWnOEaevnK2HSOYIOjnxUskE9k6mpVAOeuhRncj03nXmkq1Ae/5?= =?utf-8?q?+dH4O4qIBqm7RvpeRmRfmnRo/VeaTetxBZJj6TyOSRbfG7jNdqniTSnm3gzwVaYZ2?= =?utf-8?q?6DnVZjYjwnWHEJI062OE71haXdLBLe4J4F1FEJ/GamVWkMKR9ZS+QmJhbe7YOw1mv?= =?utf-8?q?xe0zTTnSE5Ssm47S4lLCI8aVcZjweO/ddQCUZhg9qUnihv0pjVZnxj7jm5N5TAaEd?= =?utf-8?q?zdJU88vS8QY/a8ThiWOhr/aKl9NZTomNVSfnBmk8CeKz784fj8Vm2uTlPgsvMTDBA?= =?utf-8?q?gknTmoyFPzEkO1Un15kJFJsMETcBYW0lWDGmxt3XDdKLwQjb4GHOA+snL365uTlIV?= =?utf-8?q?8YjxIKCHjk/xD28YmWwINEut4pWYiJn5PDOZVN5yTgDeF/xeDu6HZQlNMD8dJhEWN?= =?utf-8?q?myxrgJmd2BUSyPGr4z1zXWsWilXZaZEnIaNtAJTLmhLaCjiYqrqlI+BrTOebgBCLF?= =?utf-8?q?H66SlbR1PSZ3ZIxp+HmHzCB2tOA0hflARMwwhz2R2Z0RX2ljfV55KytgyqMw22REt?= =?utf-8?q?FH2FumbuUP2XcM6m/0RVv7cDFwTozZcVncgsJuPxLW+NHf51/130a+zeG8otCI6cx?= =?utf-8?q?3w9Ml4Co/jCVieCXvh/jq2D5U0W59sN0gG2GSMY8YxIVb1gbBWalbxNPCAygVQDVl?= =?utf-8?q?nR991Zob08IJR0rjo1ducb717Ak2CEnZrHQRMwPKMydD9roQfePABTbCUO9Sut9cz?= =?utf-8?q?LYt6Rq0+UUb1oETJQp3J33Kj2T6ovqm0B2QILlTFMnNWw/hyVq6rLeXRXeZlq8LAS?= =?utf-8?q?Qp6/snt0Mr5/sM7i6TNq/jri2LWrIgVqXc7q4B6+hzPA5J5chqtq4ghq76sLM67wx?= =?utf-8?q?u6i8TyUWtlCvS12nyAzq08MVV5I7xBtllJkvStVipfXR0NrP+R1599sxjDOvSMnAq?= =?utf-8?q?n+gVv8qU9aUob5xMRcQ4GH3Q+7eK/Wovn6/hXTgRL2JDD+02yvXkL4JXmcL5EtX1v?= =?utf-8?q?U6s+JmvsvVSy43xLY6QlC0QxTSqKk9+hxanCLlwnShx6qQfCIPJhQNocwj+Vh3z2L?= =?utf-8?q?m2CIYTnDya73?= X-OriginatorOrg: oss.nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 21c97aac-3bd3-484e-4035-08dc5f46575d X-MS-Exchange-CrossTenant-AuthSource: DU0PR04MB9417.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Apr 2024 01:24:49.9230 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: KqKZ0au5J/etB26Q1TlO8/MEjFG1kBDGmFLriTSH+XNbWKijr+fFDJd9w6RFFyDjtGbfo7PjNec9OTzHPQj1Yg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM7PR04MB7110 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240417_182457_731413_8342C992 X-CRM114-Status: GOOD ( 18.50 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Peng Fan scmi-pinctrl driver implements pinctrl driver interface and using SCMI protocol to redirect messages from pinctrl subsystem SDK to SCMI platform firmware, which does the changes in HW. Co-developed-by: Oleksii Moisieiev Signed-off-by: Oleksii Moisieiev Reviewed-by: Dhruva Gole Reviewed-by: Andy Shevchenko Signed-off-by: Peng Fan --- MAINTAINERS | 1 + drivers/pinctrl/Kconfig | 11 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-scmi.c | 571 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 584 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index b1b074ce2cf3..a37aaff190c7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21615,6 +21615,7 @@ F: drivers/cpufreq/sc[mp]i-cpufreq.c F: drivers/firmware/arm_scmi/ F: drivers/firmware/arm_scpi.c F: drivers/hwmon/scmi-hwmon.c +F: drivers/pinctrl/pinctrl-scmi.c F: drivers/pmdomain/arm/ F: drivers/powercap/arm_scmi_powercap.c F: drivers/regulator/scmi-regulator.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 1be05efccc29..7e4f93a3bc7a 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -450,6 +450,17 @@ config PINCTRL_ROCKCHIP help This support pinctrl and GPIO driver for Rockchip SoCs. +config PINCTRL_SCMI + tristate "Pinctrl driver using SCMI protocol interface" + depends on ARM_SCMI_PROTOCOL || COMPILE_TEST + select PINMUX + select GENERIC_PINCONF + help + This driver provides support for pinctrl which is controlled + by firmware that implements the SCMI interface. + It uses SCMI Message Protocol to interact with the + firmware providing all the pinctrl controls. + config PINCTRL_SINGLE tristate "One-register-per-pin type device tree based pinctrl driver" depends on OF diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 2152539b53d5..cc809669405a 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o +obj-$(CONFIG_PINCTRL_SCMI) += pinctrl-scmi.o obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o obj-$(CONFIG_PINCTRL_STMFX) += pinctrl-stmfx.o diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c new file mode 100644 index 000000000000..036bc1e3fc6c --- /dev/null +++ b/drivers/pinctrl/pinctrl-scmi.c @@ -0,0 +1,571 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * System Control and Power Interface (SCMI) Protocol based pinctrl driver + * + * Copyright (C) 2024 EPAM + * Copyright 2024 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "pinctrl-utils.h" +#include "core.h" +#include "pinconf.h" + +#define DRV_NAME "scmi-pinctrl" + +/* Define num configs, if not large than 4 use stack, else use kcalloc() */ +#define SCMI_NUM_CONFIGS 4 + +static const struct scmi_pinctrl_proto_ops *pinctrl_ops; + +struct scmi_pinctrl { + struct device *dev; + struct scmi_protocol_handle *ph; + struct pinctrl_dev *pctldev; + struct pinctrl_desc pctl_desc; + struct pinfunction *functions; + unsigned int nr_functions; + struct pinctrl_pin_desc *pins; + unsigned int nr_pins; +}; + +static int pinctrl_scmi_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); + + return pinctrl_ops->count_get(pmx->ph, GROUP_TYPE); +} + +static const char *pinctrl_scmi_get_group_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + int ret; + const char *name; + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); + + ret = pinctrl_ops->name_get(pmx->ph, selector, GROUP_TYPE, &name); + if (ret) { + dev_err(pmx->dev, "get name failed with err %d", ret); + return NULL; + } + + return name; +} + +static int pinctrl_scmi_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int selector, + const unsigned int **pins, + unsigned int *num_pins) +{ + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); + + return pinctrl_ops->group_pins_get(pmx->ph, selector, pins, num_pins); +} + +static const struct pinctrl_ops pinctrl_scmi_pinctrl_ops = { + .get_groups_count = pinctrl_scmi_get_groups_count, + .get_group_name = pinctrl_scmi_get_group_name, + .get_group_pins = pinctrl_scmi_get_group_pins, +#ifdef CONFIG_OF + .dt_node_to_map = pinconf_generic_dt_node_to_map_all, + .dt_free_map = pinconf_generic_dt_free_map, +#endif +}; + +static int pinctrl_scmi_get_functions_count(struct pinctrl_dev *pctldev) +{ + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); + + return pinctrl_ops->count_get(pmx->ph, FUNCTION_TYPE); +} + +static const char *pinctrl_scmi_get_function_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + int ret; + const char *name; + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); + + ret = pinctrl_ops->name_get(pmx->ph, selector, FUNCTION_TYPE, &name); + if (ret) { + dev_err(pmx->dev, "get name failed with err %d", ret); + return NULL; + } + + return name; +} + +static int pinctrl_scmi_get_function_groups(struct pinctrl_dev *pctldev, + unsigned int selector, + const char * const **p_groups, + unsigned int * const p_num_groups) +{ + struct pinfunction *func; + const unsigned int *group_ids; + unsigned int num_groups; + const char **groups; + int ret, i; + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); + + if (!p_groups || !p_num_groups) + return -EINVAL; + + if (selector >= pmx->nr_functions) + return -EINVAL; + + func = &pmx->functions[selector]; + if (func->ngroups) + goto done; + + ret = pinctrl_ops->function_groups_get(pmx->ph, selector, &num_groups, + &group_ids); + if (ret) { + dev_err(pmx->dev, "Unable to get function groups, err %d", ret); + return ret; + } + if (!num_groups) + return -EINVAL; + + groups = kcalloc(num_groups, sizeof(*groups), GFP_KERNEL); + if (!groups) + return -ENOMEM; + + for (i = 0; i < num_groups; i++) { + groups[i] = pinctrl_scmi_get_group_name(pctldev, group_ids[i]); + if (!groups[i]) { + ret = -EINVAL; + goto err_free; + } + } + + func->ngroups = num_groups; + func->groups = groups; +done: + *p_groups = func->groups; + *p_num_groups = func->ngroups; + + return 0; + +err_free: + kfree(groups); + + return ret; +} + +static int pinctrl_scmi_func_set_mux(struct pinctrl_dev *pctldev, + unsigned int selector, unsigned int group) +{ + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); + + return pinctrl_ops->mux_set(pmx->ph, selector, group); +} + +static int pinctrl_scmi_request(struct pinctrl_dev *pctldev, + unsigned int offset) +{ + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); + + return pinctrl_ops->pin_request(pmx->ph, offset); +} + +static int pinctrl_scmi_free(struct pinctrl_dev *pctldev, unsigned int offset) +{ + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); + + return pinctrl_ops->pin_free(pmx->ph, offset); +} + +static const struct pinmux_ops pinctrl_scmi_pinmux_ops = { + .request = pinctrl_scmi_request, + .free = pinctrl_scmi_free, + .get_functions_count = pinctrl_scmi_get_functions_count, + .get_function_name = pinctrl_scmi_get_function_name, + .get_function_groups = pinctrl_scmi_get_function_groups, + .set_mux = pinctrl_scmi_func_set_mux, +}; + +static int pinctrl_scmi_map_pinconf_type(enum pin_config_param param, + enum scmi_pinctrl_conf_type *type) +{ + u32 arg = param; + + switch (arg) { + case PIN_CONFIG_BIAS_BUS_HOLD: + *type = SCMI_PIN_BIAS_BUS_HOLD; + break; + case PIN_CONFIG_BIAS_DISABLE: + *type = SCMI_PIN_BIAS_DISABLE; + break; + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: + *type = SCMI_PIN_BIAS_HIGH_IMPEDANCE; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + *type = SCMI_PIN_BIAS_PULL_DOWN; + break; + case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: + *type = SCMI_PIN_BIAS_PULL_DEFAULT; + break; + case PIN_CONFIG_BIAS_PULL_UP: + *type = SCMI_PIN_BIAS_PULL_UP; + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + *type = SCMI_PIN_DRIVE_OPEN_DRAIN; + break; + case PIN_CONFIG_DRIVE_OPEN_SOURCE: + *type = SCMI_PIN_DRIVE_OPEN_SOURCE; + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + *type = SCMI_PIN_DRIVE_PUSH_PULL; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + *type = SCMI_PIN_DRIVE_STRENGTH; + break; + case PIN_CONFIG_DRIVE_STRENGTH_UA: + *type = SCMI_PIN_DRIVE_STRENGTH; + break; + case PIN_CONFIG_INPUT_DEBOUNCE: + *type = SCMI_PIN_INPUT_DEBOUNCE; + break; + case PIN_CONFIG_INPUT_ENABLE: + *type = SCMI_PIN_INPUT_MODE; + break; + case PIN_CONFIG_INPUT_SCHMITT: + *type = SCMI_PIN_INPUT_SCHMITT; + break; + case PIN_CONFIG_INPUT_SCHMITT_ENABLE: + *type = SCMI_PIN_INPUT_MODE; + break; + case PIN_CONFIG_MODE_LOW_POWER: + *type = SCMI_PIN_LOW_POWER_MODE; + break; + case PIN_CONFIG_OUTPUT: + *type = SCMI_PIN_OUTPUT_VALUE; + break; + case PIN_CONFIG_OUTPUT_ENABLE: + *type = SCMI_PIN_OUTPUT_MODE; + break; + case PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS: + *type = SCMI_PIN_OUTPUT_VALUE; + break; + case PIN_CONFIG_POWER_SOURCE: + *type = SCMI_PIN_POWER_SOURCE; + break; + case PIN_CONFIG_SLEW_RATE: + *type = SCMI_PIN_SLEW_RATE; + break; + case SCMI_PIN_OEM_START ... SCMI_PIN_OEM_END: + *type = arg; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int pinctrl_scmi_pinconf_get(struct pinctrl_dev *pctldev, + unsigned int pin, unsigned long *config) +{ + int ret; + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); + enum pin_config_param config_type; + enum scmi_pinctrl_conf_type type; + u32 config_value; + + if (!config) + return -EINVAL; + + config_type = pinconf_to_config_param(*config); + + ret = pinctrl_scmi_map_pinconf_type(config_type, &type); + if (ret) + return ret; + + ret = pinctrl_ops->settings_get_one(pmx->ph, pin, PIN_TYPE, type, + &config_value); + /* Convert SCMI error code to PINCTRL expected error code */ + if (ret == -EOPNOTSUPP) + return -ENOTSUPP; + if (ret) + return ret; + + *config = pinconf_to_config_packed(config_type, config_value); + + return 0; +} + +static int +pinctrl_scmi_alloc_configs(struct pinctrl_dev *pctldev, u32 num_configs, + u32 **p_config_value, + enum scmi_pinctrl_conf_type **p_config_type) +{ + if (num_configs <= SCMI_NUM_CONFIGS) + return 0; + + *p_config_value = kcalloc(num_configs, sizeof(**p_config_value), GFP_KERNEL); + if (!*p_config_value) + return -ENOMEM; + + *p_config_type = kcalloc(num_configs, sizeof(**p_config_type), GFP_KERNEL); + if (!*p_config_type) { + kfree(*p_config_value); + return -ENOMEM; + } + + return 0; +} + +static void +pinctrl_scmi_free_configs(struct pinctrl_dev *pctldev, u32 num_configs, + u32 **p_config_value, + enum scmi_pinctrl_conf_type **p_config_type) +{ + if (num_configs <= SCMI_NUM_CONFIGS) + return; + + kfree(*p_config_value); + kfree(*p_config_type); +} + +static int pinctrl_scmi_pinconf_set(struct pinctrl_dev *pctldev, + unsigned int pin, + unsigned long *configs, + unsigned int num_configs) +{ + int i, ret; + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); + enum scmi_pinctrl_conf_type config_type[SCMI_NUM_CONFIGS]; + u32 config_value[SCMI_NUM_CONFIGS]; + enum scmi_pinctrl_conf_type *p_config_type = config_type; + u32 *p_config_value = config_value; + enum pin_config_param param; + + if (!configs || !num_configs) + return -EINVAL; + + ret = pinctrl_scmi_alloc_configs(pctldev, num_configs, &p_config_type, + &p_config_value); + if (ret) + return ret; + + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + ret = pinctrl_scmi_map_pinconf_type(param, &p_config_type[i]); + if (ret) { + dev_err(pmx->dev, "Error map pinconf_type %d\n", ret); + goto free_config; + } + p_config_value[i] = pinconf_to_config_argument(configs[i]); + } + + ret = pinctrl_ops->settings_conf(pmx->ph, pin, PIN_TYPE, num_configs, + p_config_type, p_config_value); + if (ret) + dev_err(pmx->dev, "Error parsing config %d\n", ret); + +free_config: + pinctrl_scmi_free_configs(pctldev, num_configs, &p_config_type, + &p_config_value); + return ret; +} + +static int pinctrl_scmi_pinconf_group_set(struct pinctrl_dev *pctldev, + unsigned int group, + unsigned long *configs, + unsigned int num_configs) +{ + int i, ret; + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); + enum scmi_pinctrl_conf_type config_type[SCMI_NUM_CONFIGS]; + u32 config_value[SCMI_NUM_CONFIGS]; + enum scmi_pinctrl_conf_type *p_config_type = config_type; + u32 *p_config_value = config_value; + enum pin_config_param param; + + if (!configs || !num_configs) + return -EINVAL; + + ret = pinctrl_scmi_alloc_configs(pctldev, num_configs, &p_config_type, + &p_config_value); + if (ret) + return ret; + + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + ret = pinctrl_scmi_map_pinconf_type(param, &p_config_type[i]); + if (ret) { + dev_err(pmx->dev, "Error map pinconf_type %d\n", ret); + goto free_config; + } + + p_config_value[i] = pinconf_to_config_argument(configs[i]); + } + + ret = pinctrl_ops->settings_conf(pmx->ph, group, GROUP_TYPE, + num_configs, p_config_type, + p_config_value); + if (ret) + dev_err(pmx->dev, "Error parsing config %d", ret); + +free_config: + pinctrl_scmi_free_configs(pctldev, num_configs, &p_config_type, + &p_config_value); + return ret; +}; + +static int pinctrl_scmi_pinconf_group_get(struct pinctrl_dev *pctldev, + unsigned int group, + unsigned long *config) +{ + int ret; + struct scmi_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); + enum pin_config_param config_type; + enum scmi_pinctrl_conf_type type; + u32 config_value; + + if (!config) + return -EINVAL; + + config_type = pinconf_to_config_param(*config); + ret = pinctrl_scmi_map_pinconf_type(config_type, &type); + if (ret) { + dev_err(pmx->dev, "Error map pinconf_type %d\n", ret); + return ret; + } + + ret = pinctrl_ops->settings_get_one(pmx->ph, group, GROUP_TYPE, type, + &config_value); + /* Convert SCMI error code to PINCTRL expected error code */ + if (ret == -EOPNOTSUPP) + return -ENOTSUPP; + if (ret) + return ret; + + *config = pinconf_to_config_packed(config_type, config_value); + + return 0; +} + +static const struct pinconf_ops pinctrl_scmi_pinconf_ops = { + .is_generic = true, + .pin_config_get = pinctrl_scmi_pinconf_get, + .pin_config_set = pinctrl_scmi_pinconf_set, + .pin_config_group_set = pinctrl_scmi_pinconf_group_set, + .pin_config_group_get = pinctrl_scmi_pinconf_group_get, + .pin_config_config_dbg_show = pinconf_generic_dump_config, +}; + +static int pinctrl_scmi_get_pins(struct scmi_pinctrl *pmx, + struct pinctrl_desc *desc) +{ + struct pinctrl_pin_desc *pins; + unsigned int npins; + int ret, i; + + npins = pinctrl_ops->count_get(pmx->ph, PIN_TYPE); + /* + * npins will never be zero, the scmi pinctrl driver has bailed out + * if npins is zero. + */ + pins = devm_kmalloc_array(pmx->dev, npins, sizeof(*pins), GFP_KERNEL); + if (!pins) + return -ENOMEM; + + for (i = 0; i < npins; i++) { + pins[i].number = i; + /* + * The memory for name is handled by the scmi firmware driver, + * no need free here + */ + ret = pinctrl_ops->name_get(pmx->ph, i, PIN_TYPE, &pins[i].name); + if (ret) + return dev_err_probe(pmx->dev, ret, + "Can't get name for pin %d", i); + } + + desc->npins = npins; + desc->pins = pins; + dev_dbg(pmx->dev, "got pins %u", npins); + + return 0; +} + +static int scmi_pinctrl_probe(struct scmi_device *sdev) +{ + int ret; + struct device *dev = &sdev->dev; + struct scmi_pinctrl *pmx; + const struct scmi_handle *handle; + struct scmi_protocol_handle *ph; + + if (!sdev->handle) + return -EINVAL; + + handle = sdev->handle; + + pinctrl_ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_PINCTRL, &ph); + if (IS_ERR(pinctrl_ops)) + return PTR_ERR(pinctrl_ops); + + pmx = devm_kzalloc(dev, sizeof(*pmx), GFP_KERNEL); + if (!pmx) + return -ENOMEM; + + pmx->ph = ph; + + pmx->dev = dev; + pmx->pctl_desc.name = DRV_NAME; + pmx->pctl_desc.owner = THIS_MODULE; + pmx->pctl_desc.pctlops = &pinctrl_scmi_pinctrl_ops; + pmx->pctl_desc.pmxops = &pinctrl_scmi_pinmux_ops; + pmx->pctl_desc.confops = &pinctrl_scmi_pinconf_ops; + + ret = pinctrl_scmi_get_pins(pmx, &pmx->pctl_desc); + if (ret) + return ret; + + ret = devm_pinctrl_register_and_init(dev, &pmx->pctl_desc, pmx, + &pmx->pctldev); + if (ret) + return dev_err_probe(dev, ret, "Failed to register pinctrl\n"); + + pmx->nr_functions = pinctrl_scmi_get_functions_count(pmx->pctldev); + pmx->functions = devm_kcalloc(dev, pmx->nr_functions, + sizeof(*pmx->functions), GFP_KERNEL); + if (!pmx->functions) + return -ENOMEM; + + return pinctrl_enable(pmx->pctldev); +} + +static const struct scmi_device_id scmi_id_table[] = { + { SCMI_PROTOCOL_PINCTRL, "pinctrl" }, + { } +}; +MODULE_DEVICE_TABLE(scmi, scmi_id_table); + +static struct scmi_driver scmi_pinctrl_driver = { + .name = DRV_NAME, + .probe = scmi_pinctrl_probe, + .id_table = scmi_id_table, +}; +module_scmi_driver(scmi_pinctrl_driver); + +MODULE_AUTHOR("Oleksii Moisieiev "); +MODULE_AUTHOR("Peng Fan "); +MODULE_DESCRIPTION("ARM SCMI pin controller driver"); +MODULE_LICENSE("GPL");