From patchwork Tue Jan 19 05:27:32 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sai Krishna Potthuri X-Patchwork-Id: 366448 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1219DC433E6 for ; Tue, 19 Jan 2021 07:07:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C06F623120 for ; Tue, 19 Jan 2021 07:07:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730106AbhASHGk (ORCPT ); Tue, 19 Jan 2021 02:06:40 -0500 Received: from mail-dm6nam10on2073.outbound.protection.outlook.com ([40.107.93.73]:22753 "EHLO NAM10-DM6-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2390269AbhASF3A (ORCPT ); Tue, 19 Jan 2021 00:29:00 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=NjHTA3uXTR/84p9NIybVCicful717H4FUJUUf+dE3q9qNRTTDBdXpRc1dq3UAuo/wB1GN0cy5oxpGTyk3Sc5mfM5+h10naPGFF4OkS4uitX1gQu9naqEjQzvYbm74Wa5VSSmuRJLEyaz+bqo4dcIMu1gmFEjJFWGeCnNQgYC4jv7+A+fZgKgZm0ALz6I2MapewsTBbzksZXOlSzbsHLWk4ZvnZ0e1y7CeCnxzsKxkmAZv7s9VGUkGuMacXlCxh1yf0Dd5QSE6qzqJHqprGn9lWWwvjI7X73QtqWpOLUMtqWYzrTWzE1/9IsrdraRwi6SzSX9UEP6bl/TMdjPnTJTRw== 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-SenderADCheck; bh=MQuKc6HhhEEWxlv87rZMKTllpVHcejDU0WhNarRb3Qs=; b=K6wRpGBf0B1j5MdUx5OLhgVq99AJQKuSNe0X6UCjiUU8zuVvdnBocYgr8qVVOwfgSubHX9+0I9atdCHTaNaXqhP57/TohUfvF7opJgNFSF1mgqcDkWdj8e10bwwIn4uxS8jjBTftTY17U79ykLztIoT9mCRn5UASBhQ5RX0itSxF3LNSv8rRZyuGeV6indZ8aRZ8HvPjUCL1mxM42VlJQPGengOWNEUaAGy6m7uyJfazQTXbfQUgpV77dZMS3qgrdJd+FFDEKkJ+2szyBedVSNhKKuhaHwLxxPr8+Yqcd//IQvqFeuKqCBKXhunY7y5xbabMhvES3/1fWQYFl/2d3g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 149.199.62.198) smtp.rcpttodomain=gmail.com smtp.mailfrom=xilinx.com; dmarc=bestguesspass action=none header.from=xilinx.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xilinx.onmicrosoft.com; s=selector2-xilinx-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=MQuKc6HhhEEWxlv87rZMKTllpVHcejDU0WhNarRb3Qs=; b=RThIsdLKw8dXUcbaR7qu8yoaunVwEMQqwfKoE4UBnbjGdwgeO//jE6W/ztQL2hxBTaRNZthuLIeB2hN9opg6/4OCTX+ZnydUCSS5+9L6PQB+nRGLFLKuOzoiGfkihnQRJx44ssLpI4Z1HYxnz0RpYAXW8mMT5C7msbtHiCDOv6I= Received: from SA0PR11CA0073.namprd11.prod.outlook.com (2603:10b6:806:d2::18) by DM6PR02MB6682.namprd02.prod.outlook.com (2603:10b6:5:214::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3763.10; Tue, 19 Jan 2021 05:28:04 +0000 Received: from SN1NAM02FT034.eop-nam02.prod.protection.outlook.com (2603:10b6:806:d2:cafe::df) by SA0PR11CA0073.outlook.office365.com (2603:10b6:806:d2::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3763.10 via Frontend Transport; Tue, 19 Jan 2021 05:28:04 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 149.199.62.198) smtp.mailfrom=xilinx.com; gmail.com; dkim=none (message not signed) header.d=none;gmail.com; dmarc=bestguesspass action=none header.from=xilinx.com; Received-SPF: Pass (protection.outlook.com: domain of xilinx.com designates 149.199.62.198 as permitted sender) receiver=protection.outlook.com; client-ip=149.199.62.198; helo=xsj-pvapexch02.xlnx.xilinx.com; Received: from xsj-pvapexch02.xlnx.xilinx.com (149.199.62.198) by SN1NAM02FT034.mail.protection.outlook.com (10.152.72.141) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3763.12 via Frontend Transport; Tue, 19 Jan 2021 05:28:03 +0000 Received: from xsj-pvapexch01.xlnx.xilinx.com (172.19.86.40) by xsj-pvapexch02.xlnx.xilinx.com (172.19.86.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1913.5; Mon, 18 Jan 2021 21:27:59 -0800 Received: from smtp.xilinx.com (172.19.127.95) by xsj-pvapexch01.xlnx.xilinx.com (172.19.86.40) with Microsoft SMTP Server id 15.1.1913.5 via Frontend Transport; Mon, 18 Jan 2021 21:27:59 -0800 Envelope-to: git@xilinx.com, michal.simek@xilinx.com, saikrishna12468@gmail.com, robh+dt@kernel.org, linus.walleij@linaro.org, gregkh@linuxfoundation.org, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org Received: from [172.23.64.106] (port=37103 helo=xhdvnc125.xilinx.com) by smtp.xilinx.com with esmtp (Exim 4.90) (envelope-from ) id 1l1jYc-0003ZV-1P; Mon, 18 Jan 2021 21:27:58 -0800 Received: by xhdvnc125.xilinx.com (Postfix, from userid 14964) id 1838C1222D6; Tue, 19 Jan 2021 10:57:44 +0530 (IST) From: Sai Krishna Potthuri To: Linus Walleij , Rob Herring , Michal Simek , "Greg Kroah-Hartman" CC: , , , , , , Sai Krishna Potthuri Subject: [PATCH v2 1/3] firmware: xilinx: Added pinctrl support Date: Tue, 19 Jan 2021 10:57:32 +0530 Message-ID: <1611034054-63867-2-git-send-email-lakshmi.sai.krishna.potthuri@xilinx.com> X-Mailer: git-send-email 2.1.1 In-Reply-To: <1611034054-63867-1-git-send-email-lakshmi.sai.krishna.potthuri@xilinx.com> References: <1611034054-63867-1-git-send-email-lakshmi.sai.krishna.potthuri@xilinx.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 54d63138-8e7f-4957-80a8-08d8bc3afeba X-MS-TrafficTypeDiagnostic: DM6PR02MB6682: X-Microsoft-Antispam-PRVS: X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-MS-Oob-TLC-OOBClassifiers: OLM:247; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: z9Www9KY9blTIvdnPKRmWZFj0bQP4zojRHQsZsC1CFoXhMmr+qqNa6uCFMuBHSeVyTMxXi0Kz+ATgJGSOARnO4iFghgwwPTnxWKZuBXiSRtb5soYw2PzBBbzKZFO+tsH4m6hqZc79iCwwkPSg4CjFsHjkM8l4HRWIRnFIHUgKrJX6hYOXJrbQlmI1TUx4oqib6SD4S07n2oEWgf3FqSQ1rNwAfRaVfPRh81JV6iIZHhVzHU1F65+kDQVbET8OYqjoQKgnUQgKY5gjex5WfHtSohJYqgHBAltJY/OkvMg/a9JZSp8uEzvyrgeQeLlTSBgYJdL8AKxfcJfXHQhXCE4JsZbBUKcFOeAdEGoKbNWmsQUvABJsRzvbpk8F0Z4s/iFYyYYQrnPN3ofjzOpwhVBGbpsBlszUFZy88xlgzYsElDQPSw/RTLx3lPGySHL7ySHmEf67kxLis7E9BHJ+TH3kceh3KFkVV6R7OVa0MkHLKz+cd2BN0LsdlwMJjnfYJXe X-Forefront-Antispam-Report: CIP:149.199.62.198; CTRY:US; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:xsj-pvapexch02.xlnx.xilinx.com; PTR:unknown-62-198.xilinx.com; CAT:NONE; SFS:(4636009)(396003)(136003)(346002)(376002)(39860400002)(46966006)(2906002)(6666004)(82310400003)(316002)(36906005)(42186006)(8936002)(70206006)(36756003)(110136005)(26005)(5660300002)(70586007)(82740400003)(6266002)(478600001)(83380400001)(426003)(8676002)(4326008)(7636003)(107886003)(47076005)(336012)(2616005)(356005)(54906003)(186003)(102446001); DIR:OUT; SFP:1101; X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Jan 2021 05:28:03.9872 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 54d63138-8e7f-4957-80a8-08d8bc3afeba X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c; Ip=[149.199.62.198]; Helo=[xsj-pvapexch02.xlnx.xilinx.com] X-MS-Exchange-CrossTenant-AuthSource: SN1NAM02FT034.eop-nam02.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR02MB6682 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Add pinctrl support to query platform specific information (pins) from firmware. Signed-off-by: Sai Krishna Potthuri Acked-by: Michal Simek --- drivers/firmware/xilinx/zynqmp.c | 114 +++++++++++++++++++++++++++ include/linux/firmware/xlnx-zynqmp.h | 90 +++++++++++++++++++++ 2 files changed, 204 insertions(+) diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c index efb8a66efc68..299c3d5a9ebd 100644 --- a/drivers/firmware/xilinx/zynqmp.c +++ b/drivers/firmware/xilinx/zynqmp.c @@ -784,6 +784,120 @@ int zynqmp_pm_fpga_get_status(u32 *value) } EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status); +/** + * zynqmp_pm_pinctrl_request - Request Pin from firmware + * @pin: Pin number to request + * + * This function requests pin from firmware. + * + * Return: Returns status, either success or error+reason. + */ +int zynqmp_pm_pinctrl_request(const u32 pin) +{ + return zynqmp_pm_invoke_fn(PM_PINCTRL_REQUEST, pin, 0, 0, 0, NULL); +} +EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_request); + +/** + * zynqmp_pm_pinctrl_release - Inform firmware that Pin control is released + * @pin: Pin number to release + * + * This function release pin from firmware. + * + * Return: Returns status, either success or error+reason. + */ +int zynqmp_pm_pinctrl_release(const u32 pin) +{ + return zynqmp_pm_invoke_fn(PM_PINCTRL_RELEASE, pin, 0, 0, 0, NULL); +} +EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_release); + +/** + * zynqmp_pm_pinctrl_get_function - Read function id set for the given pin + * @pin: Pin number + * @id: Buffer to store function ID + * + * This function provides the function currently set for the given pin. + * + * Return: Returns status, either success or error+reason + */ +int zynqmp_pm_pinctrl_get_function(const u32 pin, u32 *id) +{ + u32 ret_payload[PAYLOAD_ARG_CNT]; + int ret; + + if (!id) + return -EINVAL; + + ret = zynqmp_pm_invoke_fn(PM_PINCTRL_GET_FUNCTION, pin, 0, + 0, 0, ret_payload); + *id = ret_payload[1]; + + return ret; +} +EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_function); + +/** + * zynqmp_pm_pinctrl_set_function - Set requested function for the pin + * @pin: Pin number + * @id: Function ID to set + * + * This function sets requested function for the given pin. + * + * Return: Returns status, either success or error+reason. + */ +int zynqmp_pm_pinctrl_set_function(const u32 pin, const u32 id) +{ + return zynqmp_pm_invoke_fn(PM_PINCTRL_SET_FUNCTION, pin, id, + 0, 0, NULL); +} +EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_function); + +/** + * zynqmp_pm_pinctrl_get_config - Get configuration parameter for the pin + * @pin: Pin number + * @param: Parameter to get + * @value: Buffer to store parameter value + * + * This function gets requested configuration parameter for the given pin. + * + * Return: Returns status, either success or error+reason. + */ +int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param, + u32 *value) +{ + u32 ret_payload[PAYLOAD_ARG_CNT]; + int ret; + + if (!value) + return -EINVAL; + + ret = zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_GET, pin, param, + 0, 0, ret_payload); + *value = ret_payload[1]; + + return ret; +} +EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_get_config); + +/** + * zynqmp_pm_pinctrl_set_config - Set configuration parameter for the pin + * @pin: Pin number + * @param: Parameter to set + * @value: Parameter value to set + * + * This function sets requested configuration parameter for the given pin. + * + * Return: Returns status, either success or error+reason. + */ +int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param, + u32 value) +{ + return zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_SET, pin, + param, value, 0, NULL); +} +EXPORT_SYMBOL_GPL(zynqmp_pm_pinctrl_set_config); + /** * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller * master has initialized its own power management diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h index 5968df82b991..75aa6a5afa28 100644 --- a/include/linux/firmware/xlnx-zynqmp.h +++ b/include/linux/firmware/xlnx-zynqmp.h @@ -74,6 +74,12 @@ enum pm_api_id { PM_FPGA_LOAD, PM_FPGA_GET_STATUS, PM_GET_CHIPID = 24, + PM_PINCTRL_REQUEST = 28, + PM_PINCTRL_RELEASE = 29, + PM_PINCTRL_GET_FUNCTION = 30, + PM_PINCTRL_SET_FUNCTION = 31, + PM_PINCTRL_CONFIG_PARAM_GET = 32, + PM_PINCTRL_CONFIG_PARAM_SET = 33, PM_IOCTL = 34, PM_QUERY_DATA, PM_CLOCK_ENABLE, @@ -125,6 +131,12 @@ enum pm_query_id { PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS, PM_QID_CLOCK_GET_PARENTS, PM_QID_CLOCK_GET_ATTRIBUTES, + PM_QID_PINCTRL_GET_NUM_PINS = 6, + PM_QID_PINCTRL_GET_NUM_FUNCTIONS = 7, + PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS = 8, + PM_QID_PINCTRL_GET_FUNCTION_NAME = 9, + PM_QID_PINCTRL_GET_FUNCTION_GROUPS = 10, + PM_QID_PINCTRL_GET_PIN_GROUPS = 11, PM_QID_CLOCK_GET_NUM_CLOCKS = 12, PM_QID_CLOCK_GET_MAX_DIVISOR, }; @@ -288,6 +300,44 @@ enum dll_reset_type { PM_DLL_RESET_PULSE, }; +enum pm_pinctrl_config_param { + PM_PINCTRL_CONFIG_SLEW_RATE = 0, + PM_PINCTRL_CONFIG_BIAS_STATUS = 1, + PM_PINCTRL_CONFIG_PULL_CTRL = 2, + PM_PINCTRL_CONFIG_SCHMITT_CMOS = 3, + PM_PINCTRL_CONFIG_DRIVE_STRENGTH = 4, + PM_PINCTRL_CONFIG_VOLTAGE_STATUS = 5, + PM_PINCTRL_CONFIG_TRI_STATE = 6, + PM_PINCTRL_CONFIG_MAX = 7, +}; + +enum pm_pinctrl_slew_rate { + PM_PINCTRL_SLEW_RATE_FAST = 0, + PM_PINCTRL_SLEW_RATE_SLOW = 1, +}; + +enum pm_pinctrl_bias_status { + PM_PINCTRL_BIAS_DISABLE = 0, + PM_PINCTRL_BIAS_ENABLE = 1, +}; + +enum pm_pinctrl_pull_ctrl { + PM_PINCTRL_BIAS_PULL_DOWN = 0, + PM_PINCTRL_BIAS_PULL_UP = 1, +}; + +enum pm_pinctrl_schmitt_cmos { + PM_PINCTRL_INPUT_TYPE_CMOS = 0, + PM_PINCTRL_INPUT_TYPE_SCHMITT = 1, +}; + +enum pm_pinctrl_drive_strength { + PM_PINCTRL_DRIVE_STRENGTH_2MA = 0, + PM_PINCTRL_DRIVE_STRENGTH_4MA = 1, + PM_PINCTRL_DRIVE_STRENGTH_8MA = 2, + PM_PINCTRL_DRIVE_STRENGTH_12MA = 3, +}; + enum zynqmp_pm_shutdown_type { ZYNQMP_PM_SHUTDOWN_TYPE_SHUTDOWN, ZYNQMP_PM_SHUTDOWN_TYPE_RESET, @@ -357,6 +407,14 @@ int zynqmp_pm_write_pggs(u32 index, u32 value); int zynqmp_pm_read_pggs(u32 index, u32 *value); int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype); int zynqmp_pm_set_boot_health_status(u32 value); +int zynqmp_pm_pinctrl_request(const u32 pin); +int zynqmp_pm_pinctrl_release(const u32 pin); +int zynqmp_pm_pinctrl_get_function(const u32 pin, u32 *id); +int zynqmp_pm_pinctrl_set_function(const u32 pin, const u32 id); +int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param, + u32 *value); +int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param, + u32 value); #else static inline struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void) { @@ -507,6 +565,38 @@ static inline int zynqmp_pm_set_boot_health_status(u32 value) { return -ENODEV; } + +static inline int zynqmp_pm_pinctrl_request(const u32 pin) +{ + return -ENODEV; +} + +static inline int zynqmp_pm_pinctrl_release(const u32 pin) +{ + return -ENODEV; +} + +static inline int zynqmp_pm_pinctrl_get_function(const u32 pin, u32 *id) +{ + return -ENODEV; +} + +static inline int zynqmp_pm_pinctrl_set_function(const u32 pin, const u32 id) +{ + return -ENODEV; +} + +static inline int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param, + u32 *value) +{ + return -ENODEV; +} + +static inline int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param, + u32 value) +{ + return -ENODEV; +} #endif #endif /* __FIRMWARE_ZYNQMP_H__ */ From patchwork Tue Jan 19 05:27:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sai Krishna Potthuri X-Patchwork-Id: 367386 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 07954C4332D for ; Tue, 19 Jan 2021 07:05:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B3F4023121 for ; Tue, 19 Jan 2021 07:05:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726317AbhASHFA (ORCPT ); Tue, 19 Jan 2021 02:05:00 -0500 Received: from mail-mw2nam10on2045.outbound.protection.outlook.com ([40.107.94.45]:8320 "EHLO NAM10-MW2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1731586AbhASF3S (ORCPT ); Tue, 19 Jan 2021 00:29:18 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Tk8ZSX1t7rbxM3BWC0p8BYwJ9pD+5LiBHnTunFI6vYQR0n6CkJ6Derhx9HHPaFTnp+69me9g1fHlr6/umqxfrdxnewtuudxkhM00H/vFV7+fpyiBcKejsoUC0YF3ObW3y73b2jHPSUIfVH3iQ2c9djtIohDPDVevTaQMXpmVqYtxi6b6UPTM5lN2XTXgm132x3ugxj8+iqgV22DmxheCdLoYxynh3sCSvoQvZs147c4ErwRV/HgQxqTRG4nWe8yu36HgnR1U8SdKPMFuMonCVQMQtfrlYE1j1M4j0UiT57SgQ6Ko0nlqkDoL/7uy0kOdP7LP6pgcxGSA+uxM8ocqhg== 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-SenderADCheck; bh=LhFmhOHKYUZscJUePYJoN1M0mRd5NiQGrfK7Kt36Czk=; b=FHnJXRicB8OmAtealn0f5+jxKsv9KKGxOsKlk6JRML+f8aNs5wPY8Oa0+7RnNJ02/00vN8d2OH9nGjq0p/EXkalQzO6vVAFvzfn73wpGBbHvdWXkbxamaATJfGgi6ThNWaKIy46spB6bBEYiskw9Hu8tp3hO4tdAvhBPowX3YAZtl0nIH6dEdLuTxluEKPbLBpmhVkmJmyYEAJ8GUZvbyZezH34XgwJzBkFavUR6lAZuPoleO2hc/IBYkw7cvGIvM1F7sHfozsRw3g+T9QzAUgGUWDX1fiAs3UZFr8m3S9W+CPu0WhpEHPoDoOJJXSO5k6kJsiGGeXC96Vku7PO7Zg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 149.199.62.198) smtp.rcpttodomain=gmail.com smtp.mailfrom=xilinx.com; dmarc=bestguesspass action=none header.from=xilinx.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xilinx.onmicrosoft.com; s=selector2-xilinx-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=LhFmhOHKYUZscJUePYJoN1M0mRd5NiQGrfK7Kt36Czk=; b=A/l9YAQSqn2jK8CE28AgGlZM75B72kyYdMo7sipmZAZko1TlKSFUod2VuNRVbIo3yWh3Xg4lH0nvx97WHr0xr3a96kFMi+2B5jHHoT/nqcn7GVaWGgLim0OgZ5AQaeNUH+YkR7STZNZ9OrmUdgsK1GfWn9CKMIWODIBHm/bcIBU= Received: from SN4PR0401CA0032.namprd04.prod.outlook.com (2603:10b6:803:2a::18) by MW4PR02MB7492.namprd02.prod.outlook.com (2603:10b6:303:7c::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3763.10; Tue, 19 Jan 2021 05:28:18 +0000 Received: from SN1NAM02FT057.eop-nam02.prod.protection.outlook.com (2603:10b6:803:2a:cafe::99) by SN4PR0401CA0032.outlook.office365.com (2603:10b6:803:2a::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3763.10 via Frontend Transport; Tue, 19 Jan 2021 05:28:18 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 149.199.62.198) smtp.mailfrom=xilinx.com; gmail.com; dkim=none (message not signed) header.d=none;gmail.com; dmarc=bestguesspass action=none header.from=xilinx.com; Received-SPF: Pass (protection.outlook.com: domain of xilinx.com designates 149.199.62.198 as permitted sender) receiver=protection.outlook.com; client-ip=149.199.62.198; helo=xsj-pvapexch02.xlnx.xilinx.com; Received: from xsj-pvapexch02.xlnx.xilinx.com (149.199.62.198) by SN1NAM02FT057.mail.protection.outlook.com (10.152.73.105) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3763.12 via Frontend Transport; Tue, 19 Jan 2021 05:28:18 +0000 Received: from xsj-pvapexch02.xlnx.xilinx.com (172.19.86.41) by xsj-pvapexch02.xlnx.xilinx.com (172.19.86.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1913.5; Mon, 18 Jan 2021 21:28:12 -0800 Received: from smtp.xilinx.com (172.19.127.96) by xsj-pvapexch02.xlnx.xilinx.com (172.19.86.41) with Microsoft SMTP Server id 15.1.1913.5 via Frontend Transport; Mon, 18 Jan 2021 21:28:12 -0800 Envelope-to: git@xilinx.com, michal.simek@xilinx.com, saikrishna12468@gmail.com, robh+dt@kernel.org, linus.walleij@linaro.org, gregkh@linuxfoundation.org, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org Received: from [172.23.64.106] (port=37122 helo=xhdvnc125.xilinx.com) by smtp.xilinx.com with esmtp (Exim 4.90) (envelope-from ) id 1l1jYp-0004V3-Fl; Mon, 18 Jan 2021 21:28:12 -0800 Received: by xhdvnc125.xilinx.com (Postfix, from userid 14964) id 1D0A91222D7; Tue, 19 Jan 2021 10:57:44 +0530 (IST) From: Sai Krishna Potthuri To: Linus Walleij , Rob Herring , Michal Simek , "Greg Kroah-Hartman" CC: , , , , , , Sai Krishna Potthuri Subject: [PATCH v2 2/3] dt-bindings: pinctrl: Added binding for ZynqMP pinctrl driver Date: Tue, 19 Jan 2021 10:57:33 +0530 Message-ID: <1611034054-63867-3-git-send-email-lakshmi.sai.krishna.potthuri@xilinx.com> X-Mailer: git-send-email 2.1.1 In-Reply-To: <1611034054-63867-1-git-send-email-lakshmi.sai.krishna.potthuri@xilinx.com> References: <1611034054-63867-1-git-send-email-lakshmi.sai.krishna.potthuri@xilinx.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 511397d3-c21e-483b-8aa5-08d8bc3b0733 X-MS-TrafficTypeDiagnostic: MW4PR02MB7492: X-Microsoft-Antispam-PRVS: X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-MS-Oob-TLC-OOBClassifiers: OLM:2276; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: qgDJA8NeS3WFRPCUa5L4fSFn6EOTTo/6TpNsKiUD16kKu1c/aib0HSsdMbThguxBXxeJoV5dZoQNkfyGtBLVshYKErDS7m7VPUzeCseM6nfb0sZj3CpnI9MB1/xRa5OVlNzSIsSjkRUnDlWSze5Sa1KvIF+61zIhvb9V3Lwe6NoKT8H3xqetoOc+P8eh2pQI4YYsQfZcR7Lh1AGkwpnHJ3sYkDjj/BrhFQPWiJUwY/k3fPSADrPozbb8QnGOlf/WveWG0OhEL6NzvtVVwLmA3QVt30ec7WFpp0+4XLZWm8v/LgUdRYEkevM64SAKJsi5SJl5RprBuqoY4b66y2Y6hbBCDTyvo9+8JERvRaLp8IBL3rf0v823zNKebIa1om/dzb+kWHnukRy4xewmk+lBGpFCKoorFacVNRZRcjZcgxOMPB18K4C4ECcOzgtldE7hWg1vKS74S4/FetzNGJnOyuENDzI0TSlMQRyW/ervmN3I5nMZkVedKD5g6XTdy4rkt4Bt4LxGxXDxHNu6iu9gHfdmYQX7SIrTwF66v1w3VxEMt74kmIoPjf5IchaiV2oD X-Forefront-Antispam-Report: CIP:149.199.62.198; CTRY:US; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:xsj-pvapexch02.xlnx.xilinx.com; PTR:unknown-62-198.xilinx.com; CAT:NONE; SFS:(4636009)(136003)(39860400002)(376002)(346002)(396003)(46966006)(82310400003)(6266002)(2616005)(107886003)(4326008)(70586007)(316002)(82740400003)(426003)(356005)(186003)(478600001)(8676002)(7636003)(26005)(70206006)(8936002)(966005)(47076005)(2906002)(5660300002)(36756003)(42186006)(30864003)(54906003)(110136005)(336012)(6666004)(36906005)(102446001); DIR:OUT; SFP:1101; X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Jan 2021 05:28:18.1966 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 511397d3-c21e-483b-8aa5-08d8bc3b0733 X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c; Ip=[149.199.62.198]; Helo=[xsj-pvapexch02.xlnx.xilinx.com] X-MS-Exchange-CrossTenant-AuthSource: SN1NAM02FT057.eop-nam02.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MW4PR02MB7492 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Added documentation and dt-bindings file which contains MIO pin configuration defines for Xilinx ZynqMP pinctrl driver. Signed-off-by: Sai Krishna Potthuri --- .../bindings/pinctrl/xlnx,zynqmp-pinctrl.yaml | 337 ++++++++++++++++++ include/dt-bindings/pinctrl/pinctrl-zynqmp.h | 23 ++ 2 files changed, 360 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/xlnx,zynqmp-pinctrl.yaml create mode 100644 include/dt-bindings/pinctrl/pinctrl-zynqmp.h diff --git a/Documentation/devicetree/bindings/pinctrl/xlnx,zynqmp-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/xlnx,zynqmp-pinctrl.yaml new file mode 100644 index 000000000000..9f2efbafcaa4 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/xlnx,zynqmp-pinctrl.yaml @@ -0,0 +1,337 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/xlnx,zynqmp-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Xilinx ZynqMP Pinctrl + +maintainers: + - Sai Krishna Potthuri + - Rajan Vaja + +description: | + Please refer to pinctrl-bindings.txt in this directory for details of the + common pinctrl bindings used by client devices, including the meaning of the + phrase "pin configuration node". + + ZynqMP's pin configuration nodes act as a container for an arbitrary number of + subnodes. Each of these subnodes represents some desired configuration for a + pin, a group, or a list of pins or groups. This configuration can include the + mux function to select on those pin(s)/group(s), and various pin configuration + parameters, such as pull-up, slew rate, etc. + + Each configuration node can consist of multiple nodes describing the pinmux and + pinconf options. Those nodes can be pinmux nodes or pinconf nodes. + + The name of each subnode is not important; all subnodes should be enumerated + and processed purely based on their content. + +properties: + compatible: + const: xlnx,zynqmp-pinctrl + +patternProperties: + '^(.*-)?(default|gpio)$': + type: object + patternProperties: + '^mux(.*)$': + type: object + description: + Pinctrl node's client devices use subnodes for pin muxes, + which in turn use below standard properties. + $ref: pinmux-node.yaml# + + properties: + groups: + description: + List of groups to select (either this or "pins" must be + specified), available groups for this subnode. + items: + oneOf: + - enum: [ethernet0_0_grp, ethernet1_0_grp, ethernet2_0_grp, + ethernet3_0_grp, gemtsu0_0_grp, gemtsu0_1_grp, + gemtsu0_2_grp, mdio0_0_grp, mdio1_0_grp, + mdio1_1_grp, mdio2_0_grp, mdio3_0_grp, + qspi0_0_grp, qspi_ss_0_grp, qspi_fbclk_0_grp, + spi0_0_grp, spi0_ss_0_grp, spi0_ss_1_grp, + spi0_ss_2_grp, spi0_1_grp, spi0_ss_3_grp, + spi0_ss_4_grp, spi0_ss_5_grp, spi0_2_grp, + spi0_ss_6_grp, spi0_ss_7_grp, spi0_ss_8_grp, + spi0_3_grp, spi0_ss_9_grp, spi0_ss_10_grp, + spi0_ss_11_grp, spi0_4_grp, spi0_ss_12_grp, + spi0_ss_13_grp, spi0_ss_14_grp, spi0_5_grp, + spi0_ss_15_grp, spi0_ss_16_grp, spi0_ss_17_grp, + spi1_0_grp, spi1_ss_0_grp, spi1_ss_1_grp, + spi1_ss_2_grp, spi1_1_grp, spi1_ss_3_grp, + spi1_ss_4_grp, spi1_ss_5_grp, spi1_2_grp, + spi1_ss_6_grp, spi1_ss_7_grp, spi1_ss_8_grp, + spi1_3_grp, spi1_ss_9_grp, spi1_ss_10_grp, + spi1_ss_11_grp, spi1_4_grp, spi1_ss_12_grp, + spi1_ss_13_grp, spi1_ss_14_grp, spi1_5_grp, + spi1_ss_15_grp, spi1_ss_16_grp, spi1_ss_17_grp, + sdio0_0_grp, sdio0_1_grp, sdio0_2_grp, + sdio0_3_grp, sdio0_4_grp, sdio0_5_grp, + sdio0_6_grp, sdio0_7_grp, sdio0_8_grp, + sdio0_9_grp, sdio0_10_grp, sdio0_11_grp, + sdio0_12_grp, sdio0_13_grp, sdio0_14_grp, + sdio0_15_grp, sdio0_16_grp, sdio0_17_grp, + sdio0_18_grp, sdio0_19_grp, sdio0_20_grp, + sdio0_21_grp, sdio0_22_grp, sdio0_23_grp, + sdio0_24_grp, sdio0_25_grp, sdio0_26_grp, + sdio0_27_grp, sdio0_28_grp, sdio0_29_grp, + sdio0_30_grp, sdio0_31_grp, sdio0_32_grp, + sdio0_pc_0_grp, sdio0_cd_0_grp, sdio0_wp_0_grp, + sdio0_pc_1_grp, sdio0_cd_1_grp, sdio0_wp_1_grp, + sdio0_pc_2_grp, sdio0_cd_2_grp, sdio0_wp_2_grp, + sdio1_0_grp, sdio1_1_grp, sdio1_2_grp, + sdio1_3_grp, sdio1_4_grp, sdio1_5_grp, + sdio1_6_grp, sdio1_7_grp, sdio1_8_grp, + sdio1_9_grp, sdio1_10_grp, sdio1_11_grp, + sdio1_12_grp, sdio1_13_grp, sdio1_14_grp, + sdio1_15_grp, sdio1_pc_0_grp, sdio1_cd_0_grp, + sdio1_wp_0_grp, sdio1_pc_1_grp, sdio1_cd_1_grp, + sdio1_wp_1_grp, nand0_0_grp, nand0_ce_0_grp, + nand0_rb_0_grp, nand0_dqs_0_grp, nand0_ce_1_grp, + nand0_rb_1_grp, nand0_dqs_1_grp, can0_0_grp, + can0_1_grp, can0_2_grp, can0_3_grp, + can0_4_grp, can0_5_grp, can0_6_grp, + can0_7_grp, can0_8_grp, can0_9_grp, + can0_10_grp, can0_11_grp, can0_12_grp, + can0_13_grp, can0_14_grp, can0_15_grp, + can0_16_grp, can0_17_grp, can0_18_grp, + can1_0_grp, can1_1_grp, can1_2_grp, + can1_3_grp, can1_4_grp, can1_5_grp, + can1_6_grp, can1_7_grp, can1_8_grp, + can1_9_grp, can1_10_grp, can1_11_grp, + can1_12_grp, can1_13_grp, can1_14_grp, + can1_15_grp, can1_16_grp, can1_17_grp, + can1_18_grp, can1_19_grp, uart0_0_grp, + uart0_1_grp, uart0_2_grp, uart0_3_grp, + uart0_4_grp, uart0_5_grp, uart0_6_grp, + uart0_7_grp, uart0_8_grp, uart0_9_grp, + uart0_10_grp, uart0_11_grp, uart0_12_grp, + uart0_13_grp, uart0_14_grp, uart0_15_grp, + uart0_16_grp, uart0_17_grp, uart0_18_grp, + uart1_0_grp, uart1_1_grp, uart1_2_grp, + uart1_3_grp, uart1_4_grp, uart1_5_grp, + uart1_6_grp, uart1_7_grp, uart1_8_grp, + uart1_9_grp, uart1_10_grp, uart1_11_grp, + uart1_12_grp, uart1_13_grp, uart1_14_grp, + uart1_15_grp, uart1_16_grp, uart1_17_grp, + uart1_18_grp, i2c0_0_grp, i2c0_1_grp, + i2c0_2_grp, i2c0_3_grp, i2c0_4_grp, + i2c0_5_grp, i2c0_6_grp, i2c0_7_grp, + i2c0_8_grp, i2c0_9_grp, i2c0_10_grp, + i2c0_11_grp, i2c0_12_grp, i2c0_13_grp, + i2c0_14_grp, i2c0_15_grp, i2c0_16_grp, + i2c0_17_grp, i2c0_18_grp, i2c1_0_grp, + i2c1_1_grp, i2c1_2_grp, i2c1_3_grp, + i2c1_4_grp, i2c1_5_grp, i2c1_6_grp, + i2c1_7_grp, i2c1_8_grp, i2c1_9_grp, + i2c1_10_grp, i2c1_11_grp, i2c1_12_grp, + i2c1_13_grp, i2c1_14_grp, i2c1_15_grp, + i2c1_16_grp, i2c1_17_grp, i2c1_18_grp, + i2c1_19_grp, ttc0_clk_0_grp, ttc0_wav_0_grp, + ttc0_clk_1_grp, ttc0_wav_1_grp, ttc0_clk_2_grp, + ttc0_wav_2_grp, ttc0_clk_3_grp, ttc0_wav_3_grp, + ttc0_clk_4_grp, ttc0_wav_4_grp, ttc0_clk_5_grp, + ttc0_wav_5_grp, ttc0_clk_6_grp, ttc0_wav_6_grp, + ttc0_clk_7_grp, ttc0_wav_7_grp, ttc0_clk_8_grp, + ttc0_wav_8_grp, ttc1_clk_0_grp, ttc1_wav_0_grp, + ttc1_clk_1_grp, ttc1_wav_1_grp, ttc1_clk_2_grp, + ttc1_wav_2_grp, ttc1_clk_3_grp, ttc1_wav_3_grp, + ttc1_clk_4_grp, ttc1_wav_4_grp, ttc1_clk_5_grp, + ttc1_wav_5_grp, ttc1_clk_6_grp, ttc1_wav_6_grp, + ttc1_clk_7_grp, ttc1_wav_7_grp, ttc1_clk_8_grp, + ttc1_wav_8_grp, ttc2_clk_0_grp, ttc2_wav_0_grp, + ttc2_clk_1_grp, ttc2_wav_1_grp, ttc2_clk_2_grp, + ttc2_wav_2_grp, ttc2_clk_3_grp, ttc2_wav_3_grp, + ttc2_clk_4_grp, ttc2_wav_4_grp, ttc2_clk_5_grp, + ttc2_wav_5_grp, ttc2_clk_6_grp, ttc2_wav_6_grp, + ttc2_clk_7_grp, ttc2_wav_7_grp, ttc2_clk_8_grp, + ttc2_wav_8_grp, ttc3_clk_0_grp, ttc3_wav_0_grp, + ttc3_clk_1_grp, ttc3_wav_1_grp, ttc3_clk_2_grp, + ttc3_wav_2_grp, ttc3_clk_3_grp, ttc3_wav_3_grp, + ttc3_clk_4_grp, ttc3_wav_4_grp, ttc3_clk_5_grp, + ttc3_wav_5_grp, ttc3_clk_6_grp, ttc3_wav_6_grp, + ttc3_clk_7_grp, ttc3_wav_7_grp, ttc3_clk_8_grp, + ttc3_wav_8_grp, swdt0_clk_0_grp, swdt0_rst_0_grp, + swdt0_clk_1_grp, swdt0_rst_1_grp, swdt0_clk_2_grp, + swdt0_rst_2_grp, swdt0_clk_3_grp, swdt0_rst_3_grp, + swdt0_clk_4_grp, swdt0_rst_4_grp, swdt0_clk_5_grp, + swdt0_rst_5_grp, swdt0_clk_6_grp, swdt0_rst_6_grp, + swdt0_clk_7_grp, swdt0_rst_7_grp, swdt0_clk_8_grp, + swdt0_rst_8_grp, swdt0_clk_9_grp, swdt0_rst_9_grp, + swdt0_clk_10_grp, swdt0_rst_10_grp, swdt0_clk_11_grp, + swdt0_rst_11_grp, swdt0_clk_12_grp, swdt0_rst_12_grp, + swdt1_clk_0_grp, swdt1_rst_0_grp, swdt1_clk_1_grp, + swdt1_rst_1_grp, swdt1_clk_2_grp, swdt1_rst_2_grp, + swdt1_clk_3_grp, swdt1_rst_3_grp, swdt1_clk_4_grp, + swdt1_rst_4_grp, swdt1_clk_5_grp, swdt1_rst_5_grp, + swdt1_clk_6_grp, swdt1_rst_6_grp, swdt1_clk_7_grp, + swdt1_rst_7_grp, swdt1_clk_8_grp, swdt1_rst_8_grp, + swdt1_clk_9_grp, swdt1_rst_9_grp, swdt1_clk_10_grp, + swdt1_rst_10_grp, swdt1_clk_11_grp, swdt1_rst_11_grp, + swdt1_clk_12_grp, swdt1_rst_12_grp, gpio0_0_grp, + gpio0_1_grp, gpio0_2_grp, gpio0_3_grp, + gpio0_4_grp, gpio0_5_grp, gpio0_6_grp, + gpio0_7_grp, gpio0_8_grp, gpio0_9_grp, + gpio0_10_grp, gpio0_11_grp, gpio0_12_grp, + gpio0_13_grp, gpio0_14_grp, gpio0_15_grp, + gpio0_16_grp, gpio0_17_grp, gpio0_18_grp, + gpio0_19_grp, gpio0_20_grp, gpio0_21_grp, + gpio0_22_grp, gpio0_23_grp, gpio0_24_grp, + gpio0_25_grp, gpio0_26_grp, gpio0_27_grp, + gpio0_28_grp, gpio0_29_grp, gpio0_30_grp, + gpio0_31_grp, gpio0_32_grp, gpio0_33_grp, + gpio0_34_grp, gpio0_35_grp, gpio0_36_grp, + gpio0_37_grp, gpio0_38_grp, gpio0_39_grp, + gpio0_40_grp, gpio0_41_grp, gpio0_42_grp, + gpio0_43_grp, gpio0_44_grp, gpio0_45_grp, + gpio0_46_grp, gpio0_47_grp, gpio0_48_grp, + gpio0_49_grp, gpio0_50_grp, gpio0_51_grp, + gpio0_52_grp, gpio0_53_grp, gpio0_54_grp, + gpio0_55_grp, gpio0_56_grp, gpio0_57_grp, + gpio0_58_grp, gpio0_59_grp, gpio0_60_grp, + gpio0_61_grp, gpio0_62_grp, gpio0_63_grp, + gpio0_64_grp, gpio0_65_grp, gpio0_66_grp, + gpio0_67_grp, gpio0_68_grp, gpio0_69_grp, + gpio0_70_grp, gpio0_71_grp, gpio0_72_grp, + gpio0_73_grp, gpio0_74_grp, gpio0_75_grp, + gpio0_76_grp, gpio0_77_grp, usb0_0_grp, + usb1_0_grp, pmu0_0_grp, pmu0_1_grp, + pmu0_2_grp, pmu0_3_grp, pmu0_4_grp, + pmu0_5_grp, pmu0_6_grp, pmu0_7_grp, + pmu0_8_grp, pmu0_9_grp, pmu0_10_grp, + pmu0_11_grp, pcie0_0_grp, pcie0_1_grp, + pcie0_2_grp, pcie0_3_grp, pcie0_4_grp, + pcie0_5_grp, pcie0_6_grp, pcie0_7_grp, + csu0_0_grp, csu0_1_grp, csu0_2_grp, + csu0_3_grp, csu0_4_grp, csu0_5_grp, + csu0_6_grp, csu0_7_grp, csu0_8_grp, + csu0_9_grp, csu0_10_grp, csu0_11_grp, + dpaux0_0_grp, dpaux0_1_grp, dpaux0_2_grp, + dpaux0_3_grp, pjtag0_0_grp, pjtag0_1_grp, + pjtag0_2_grp, pjtag0_3_grp, pjtag0_4_grp, + pjtag0_5_grp, trace0_0_grp, trace0_clk_0_grp, + trace0_1_grp, trace0_clk_1_grp, trace0_2_grp, + trace0_clk_2_grp, testscan0_0_grp] + + function: + description: + Specify the alternative function to be configured for the + given pin groups. + enum: [ethernet0, ethernet1, ethernet2, ethernet3, gemtsu0, usb0, usb1, mdio0, + mdio1, mdio2, mdio3, qspi0, qspi_fbclk, qspi_ss, spi0, spi1, spi0_ss, + spi1_ss, sdio0, sdio0_pc, sdio0_wp, sdio0_cd, sdio1, sdio1_pc, sdio1_wp, + sdio1_cd, nand0, nand0_ce, nand0_rb, nand0_dqs, can0, can1, uart0, uart1, + i2c0, i2c1, ttc0_clk, ttc0_wav, ttc1_clk, ttc1_wav, ttc2_clk, ttc2_wav, + ttc3_clk, ttc3_wav, swdt0_clk, swdt0_rst, swdt1_clk, swdt1_rst, gpio0, pmu0, + pcie0, csu0, dpaux0, pjtag0, trace0, trace0_clk, testscan0] + + required: + - groups + - function + + additionalProperties: false + + '^conf(.*)$': + type: object + description: + Pinctrl node's client devices use subnodes for pin configurations, + which in turn use the standard properties below. + $ref: pincfg-node.yaml# + + properties: + groups: + description: + List of pin groups as mentioned above (either this or "pins" must + be specified). + + pins: + description: + List of pin names to select in this subnode (either this or "groups" must + be specified) + items: + oneOf: + - pattern: '^MIO([0-9]|[1-6][0-9]|7[0-7])$' + + bias-pull-up: true + + bias-pull-down: true + + bias-disable: true + + input-schmitt-enable: true + + input-schmitt-disable: true + + bias-high-impedance: true + + low-power-enable: true + + low-power-disable: true + + slew-rate: + enum: [0, 1] + + drive-strength: + description: + Selects the drive strength for MIO pins, in mA. + enum: [2, 4, 8, 12] + + io-standard: + description: + Selects the IO standard for MIO pins, this is driver specific. + $ref: "/schemas/types.yaml#/definitions/uint32" + enum: [0, 1] + + additionalProperties: false + + additionalProperties: false + +required: + - compatible + +additionalProperties: false + +examples: + - | + #include + zynqmp_firmware: zynqmp-firmware { + pinctrl0: pinctrl { + compatible = "xlnx,zynqmp-pinctrl"; + + pinctrl_uart1_default: uart1-default { + mux { + groups = "uart0_4_grp", "uart0_5_grp"; + function = "uart0"; + }; + + conf { + groups = "uart0_4_grp"; + slew-rate = ; + io-standard = ; + }; + + conf-rx { + pins = "MIO18"; + bias-pull-up; + }; + + conf-tx { + pins = "MIO19"; + bias-disable; + input-schmitt-disable; + }; + }; + }; + }; + + uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1_default>; + }; + +... diff --git a/include/dt-bindings/pinctrl/pinctrl-zynqmp.h b/include/dt-bindings/pinctrl/pinctrl-zynqmp.h new file mode 100644 index 000000000000..b73b0ae2f90b --- /dev/null +++ b/include/dt-bindings/pinctrl/pinctrl-zynqmp.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * MIO pin configuration defines for Xilinx ZynqMP + * + * Copyright (C) 2020 Xilinx, Inc. + */ + +#ifndef _DT_BINDINGS_PINCTRL_ZYNQMP_H +#define _DT_BINDINGS_PINCTRL_ZYNQMP_H + +/* Bit value for IO standards */ +#define IO_STANDARD_LVCMOS33 0 +#define IO_STANDARD_LVCMOS18 1 + +/* Bit values for Slew Rates */ +#define SLEW_RATE_FAST 0 +#define SLEW_RATE_SLOW 1 + +/* Bit values for Pin inputs */ +#define PIN_INPUT_TYPE_CMOS 0 +#define PIN_INPUT_TYPE_SCHMITT 1 + +#endif /* _DT_BINDINGS_PINCTRL_ZYNQMP_H */ From patchwork Tue Jan 19 05:27:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sai Krishna Potthuri X-Patchwork-Id: 366449 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4B63AC433E6 for ; Tue, 19 Jan 2021 06:57:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F28D023123 for ; Tue, 19 Jan 2021 06:57:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729511AbhASG4f (ORCPT ); Tue, 19 Jan 2021 01:56:35 -0500 Received: from mail-mw2nam10on2045.outbound.protection.outlook.com ([40.107.94.45]:5729 "EHLO NAM10-MW2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2390337AbhASF3p (ORCPT ); Tue, 19 Jan 2021 00:29:45 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=G3O9FGqMbKA11k71YzolBF78kiVREvrHmRK7et8Nn9e6s78sztWTdVEP2uGp6MTFjANspFcK8D9MKWK0hOQMWo/o3bYrvGEkfyAjEy4O0DGKd8sitpV2Z/YdapNzVfNs1/6JjF6Xchnd5xKzRhwsgvFajPQKMIGEDGy1e3JYAxSJhXDVmljvF+0OX+teTOXyoAWPuecxwpO9j8lQSw1d9bchb/ypKurOvbRd+ZOp3+5Zw56UtsAanT+vOy+4N6hu7mF9io/QEthngIgeeI4wj14X+MxPyrG3+Yp/9rY8pqO9dlgDqrOhEF7hpSgDq+baXUsk8dimGeuiDuij+C2EzQ== 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-SenderADCheck; bh=Rc+0/+ohxkmmqy9lqTcyBKERLtM/Kb0exCp8ZnG+6lE=; b=CPuNZA9t33F9VxIYMputspZfgQhQooNoDzd3jeFOK9op5a31h21A39RaMdKNOkhxsmplYnzeh7x578tdIudLbsmvNeQtDlzAFbiTxFGB4rEX7WShw5SSgK+9hsOD+zhws73UANfrolJ5Bu/SOLSmbU+4Rxdays1/u19BaU6d9BRR4pYbQ/zmNm2QgxnL/1deI7rk7YTPsl6iTFhZZYmyMTGw6lyASdPm1j5M+Rs3q0H98ApQHYbjZ3eXkbJ35/F85W4VCPaawMJOUhPSDbJOBdo6Oz+IXs3BtClI7vVqEOM+gvLUqG0ncfMpoCSEeq5Ixm+J58S9BFwEV/IcCWhc1g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 149.199.62.198) smtp.rcpttodomain=gmail.com smtp.mailfrom=xilinx.com; dmarc=bestguesspass action=none header.from=xilinx.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=xilinx.onmicrosoft.com; s=selector2-xilinx-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Rc+0/+ohxkmmqy9lqTcyBKERLtM/Kb0exCp8ZnG+6lE=; b=p9i8tu63upgCKkoSSWiSlVHODdLP74vqn78zpoc0BK269NdkppHySEAocpeGjojtwSxMZZJGIheqRrDpgmztKfGpxSHUxocfz5l1IEZfayJh9G1XmPuYttL7RtXu7YTwEw7L2JE6iNxEcjV4c/CLMeqWUUQN6LKV8aAn739pSL0= Received: from SN4PR0601CA0023.namprd06.prod.outlook.com (2603:10b6:803:2f::33) by MWHPR02MB2797.namprd02.prod.outlook.com (2603:10b6:300:106::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3763.10; Tue, 19 Jan 2021 05:28:47 +0000 Received: from SN1NAM02FT038.eop-nam02.prod.protection.outlook.com (2603:10b6:803:2f:cafe::90) by SN4PR0601CA0023.outlook.office365.com (2603:10b6:803:2f::33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3763.10 via Frontend Transport; Tue, 19 Jan 2021 05:28:47 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 149.199.62.198) smtp.mailfrom=xilinx.com; gmail.com; dkim=none (message not signed) header.d=none;gmail.com; dmarc=bestguesspass action=none header.from=xilinx.com; Received-SPF: Pass (protection.outlook.com: domain of xilinx.com designates 149.199.62.198 as permitted sender) receiver=protection.outlook.com; client-ip=149.199.62.198; helo=xsj-pvapexch01.xlnx.xilinx.com; Received: from xsj-pvapexch01.xlnx.xilinx.com (149.199.62.198) by SN1NAM02FT038.mail.protection.outlook.com (10.152.72.69) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.3763.12 via Frontend Transport; Tue, 19 Jan 2021 05:28:47 +0000 Received: from xsj-pvapexch01.xlnx.xilinx.com (172.19.86.40) by xsj-pvapexch01.xlnx.xilinx.com (172.19.86.40) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1913.5; Mon, 18 Jan 2021 21:28:26 -0800 Received: from smtp.xilinx.com (172.19.127.95) by xsj-pvapexch01.xlnx.xilinx.com (172.19.86.40) with Microsoft SMTP Server id 15.1.1913.5 via Frontend Transport; Mon, 18 Jan 2021 21:28:26 -0800 Envelope-to: git@xilinx.com, michal.simek@xilinx.com, saikrishna12468@gmail.com, robh+dt@kernel.org, linus.walleij@linaro.org, gregkh@linuxfoundation.org, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org Received: from [172.23.64.106] (port=37124 helo=xhdvnc125.xilinx.com) by smtp.xilinx.com with esmtp (Exim 4.90) (envelope-from ) id 1l1jZ3-0003b5-5G; Mon, 18 Jan 2021 21:28:26 -0800 Received: by xhdvnc125.xilinx.com (Postfix, from userid 14964) id 23E951222D8; Tue, 19 Jan 2021 10:57:44 +0530 (IST) From: Sai Krishna Potthuri To: Linus Walleij , Rob Herring , Michal Simek , "Greg Kroah-Hartman" CC: , , , , , , Sai Krishna Potthuri Subject: [PATCH v2 3/3] pinctrl: Added Xilinx ZynqMP pinctrl driver support Date: Tue, 19 Jan 2021 10:57:34 +0530 Message-ID: <1611034054-63867-4-git-send-email-lakshmi.sai.krishna.potthuri@xilinx.com> X-Mailer: git-send-email 2.1.1 In-Reply-To: <1611034054-63867-1-git-send-email-lakshmi.sai.krishna.potthuri@xilinx.com> References: <1611034054-63867-1-git-send-email-lakshmi.sai.krishna.potthuri@xilinx.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: b68114fb-cd84-4448-a672-08d8bc3b1863 X-MS-TrafficTypeDiagnostic: MWHPR02MB2797: X-Microsoft-Antispam-PRVS: X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-MS-Oob-TLC-OOBClassifiers: OLM:222; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: rfGXTwLhfCrynzK0mI4Fd2ckPagLS/AiKKLu91dRrf8fyC4AlV58R8+YNv4b0fTtZvgHdTMhiIKqjT/OjAXpFGi3QWYnRzis37w74gOYIki6kcW9o+W7EF6I8R5qij9VAvFPjMVhxUvB81wRkkanPXlhBwvftVbsorcY/xDZnhx8OxDcvWDdPmNRbdEmR8A1xXy+D/ZWFaHErqHsu53eXTH+QfGkBlv/9B38cfZWFaHUtH48WoVlUqk5yGy6qXcSSMTINkrSmdcyuEYTn0kgUBXz3u6CHjupGlOz+IVBHPrQso82ymTgLk4PevgnkSEX2xy0uHdcLDh0h1tOzFb6oU1vBF/0/EOWNk+Ye0BIgFIx5p8dGJSZLv8+rsCzf2Es+gZyU25mbNn6LqRD/Ym6CXSUYe/qyTRyJUAjCim1+6O3vEgc9MPdFuIjb05oQjkJGUx7PKUi3anNrsECQM88U4PYT2wYy47fblo5K1V9k1Gsw4Kqkji45KUtFbyIRp1j X-Forefront-Antispam-Report: CIP:149.199.62.198; CTRY:US; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:xsj-pvapexch01.xlnx.xilinx.com; PTR:unknown-62-198.xilinx.com; CAT:NONE; SFS:(4636009)(376002)(346002)(39860400002)(136003)(396003)(46966006)(8676002)(478600001)(107886003)(42186006)(83380400001)(356005)(82740400003)(36756003)(336012)(7636003)(2906002)(426003)(6266002)(82310400003)(4326008)(26005)(2616005)(186003)(6666004)(8936002)(5660300002)(110136005)(70586007)(316002)(54906003)(36906005)(70206006)(47076005)(30864003)(102446001); DIR:OUT; SFP:1101; X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Jan 2021 05:28:47.0381 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: b68114fb-cd84-4448-a672-08d8bc3b1863 X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c; Ip=[149.199.62.198]; Helo=[xsj-pvapexch01.xlnx.xilinx.com] X-MS-Exchange-CrossTenant-AuthSource: SN1NAM02FT038.eop-nam02.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR02MB2797 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Added pinctrl driver for Xilinx ZynqMP platform. This driver queries pin information from firmware and registers pin control accordingly. Signed-off-by: Sai Krishna Potthuri --- drivers/pinctrl/Kconfig | 13 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-zynqmp.c | 1031 ++++++++++++++++++++++++++++++ 3 files changed, 1045 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-zynqmp.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 815095326e2d..25d3c7208975 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -341,6 +341,19 @@ config PINCTRL_ZYNQ help This selects the pinctrl driver for Xilinx Zynq. +config PINCTRL_ZYNQMP + bool "Pinctrl driver for Xilinx ZynqMP" + depends on ARCH_ZYNQMP + select PINMUX + select GENERIC_PINCONF + help + This selects the pinctrl driver for Xilinx ZynqMP platform. + This driver will query the pin information from the firmware + and allow configuring the pins. + Configuration can include the mux function to select on those + pin(s)/group(s), and various pin configuration parameters + such as pull-up, slew rate, etc. + config PINCTRL_INGENIC bool "Pinctrl driver for the Ingenic JZ47xx SoCs" default MACH_INGENIC diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index f53933b2ff02..7e058739f0d5 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o obj-$(CONFIG_PINCTRL_STMFX) += pinctrl-stmfx.o obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o +obj-$(CONFIG_PINCTRL_ZYNQMP) += pinctrl-zynqmp.o obj-$(CONFIG_PINCTRL_INGENIC) += pinctrl-ingenic.o obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o obj-$(CONFIG_PINCTRL_OCELOT) += pinctrl-ocelot.o diff --git a/drivers/pinctrl/pinctrl-zynqmp.c b/drivers/pinctrl/pinctrl-zynqmp.c new file mode 100644 index 000000000000..ec0a5d0e22d5 --- /dev/null +++ b/drivers/pinctrl/pinctrl-zynqmp.c @@ -0,0 +1,1031 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ZynqMP pin controller + * + * Copyright (C) 2020 Xilinx, Inc. + * + * Sai Krishna Potthuri + * Rajan Vaja + */ + +#include +#include +#include +#include +#include +#include +#include +#include "core.h" +#include "pinctrl-utils.h" + +#define ZYNQMP_PIN_PREFIX "MIO" +#define PINCTRL_GET_FUNC_NAME_RESP_LEN 16 +#define MAX_FUNC_NAME_LEN 16 +#define MAX_GROUP_PIN 50 +#define END_OF_FUNCTIONS "END_OF_FUNCTIONS" +#define NUM_GROUPS_PER_RESP 6 + +#define PINCTRL_GET_FUNC_GROUPS_RESP_LEN 12 +#define PINCTRL_GET_PIN_GROUPS_RESP_LEN 12 +#define NA_GROUP -1 +#define RESERVED_GROUP -2 + +#define DRIVE_STRENGTH_2MA 2 +#define DRIVE_STRENGTH_4MA 4 +#define DRIVE_STRENGTH_8MA 8 +#define DRIVE_STRENGTH_12MA 12 + +/** + * struct zynqmp_pmux_function - a pinmux function + * @name: Name of the pinmux function + * @groups: List of pingroups for this function + * @ngroups: Number of entries in @groups + * @node:` Firmware node matching with for function + * + * This structure holds information about pin control function + * and function group names supporting that function. + */ +struct zynqmp_pmux_function { + char name[MAX_FUNC_NAME_LEN]; + const char * const *groups; + unsigned int ngroups; +}; + +/** + * struct zynqmp_pinctrl - driver data + * @pctrl: Pinctrl device + * @groups: Pingroups + * @ngroups: Number of @groups + * @funcs: Pinmux functions + * @nfuncs: Number of @funcs + * + * This struct is stored as driver data and used to retrieve + * information regarding pin control functions, groups and + * group pins. + */ +struct zynqmp_pinctrl { + struct pinctrl_dev *pctrl; + const struct zynqmp_pctrl_group *groups; + unsigned int ngroups; + const struct zynqmp_pmux_function *funcs; + unsigned int nfuncs; +}; + +/** + * struct zynqmp_pctrl_group - Pin control group info + * @name: Group name + * @pins: Group pin numbers + * @npins: Number of pins in group + */ +struct zynqmp_pctrl_group { + const char *name; + unsigned int pins[MAX_GROUP_PIN]; + unsigned int npins; +}; + +/** + * enum zynqmp_pin_config_param - possible pin configuration parameters + * @PIN_CONFIG_IOSTANDARD: if the pin can select an IO standard, + * the argument to this parameter (on a + * custom format) tells the driver which + * alternative IO standard to use + */ +enum zynqmp_pin_config_param { + PIN_CONFIG_IOSTANDARD = PIN_CONFIG_END + 1, +}; + +static const struct pinconf_generic_params zynqmp_dt_params[] = { + {"io-standard", PIN_CONFIG_IOSTANDARD, IO_STANDARD_LVCMOS18}, +}; + +#ifdef CONFIG_DEBUG_FS +static const struct +pin_config_item zynqmp_conf_items[ARRAY_SIZE(zynqmp_dt_params)] = { + PCONFDUMP(PIN_CONFIG_IOSTANDARD, "io-standard", NULL, true), +}; +#endif + +static struct pinctrl_desc zynqmp_desc; + +/** + * zynqmp_pctrl_get_groups_count() - get group count + * @pctldev: Pincontrol device pointer. + * + * Get total groups count. + * + * Return: group count. + */ +static int zynqmp_pctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + return pctrl->ngroups; +} + +/** + * zynqmp_pctrl_get_group_name() - get group name + * @pctldev: Pincontrol device pointer. + * @selector: Group ID. + * + * Get gorup's name. + * + * Return: group name. + */ +static const char *zynqmp_pctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + return pctrl->groups[selector].name; +} + +/** + * zynqmp_pctrl_get_group_pins() - get group pins + * @pctldev: Pincontrol device pointer. + * @selector: Group ID. + * @pins: Pin numbers. + * @npins: Number of pins in group. + * + * Get gorup's pin count and pin number. + * + * Return: Success. + */ +static int zynqmp_pctrl_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int selector, + const unsigned int **pins, + unsigned int *npins) +{ + struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + *pins = pctrl->groups[selector].pins; + *npins = pctrl->groups[selector].npins; + + return 0; +} + +static const struct pinctrl_ops zynqmp_pctrl_ops = { + .get_groups_count = zynqmp_pctrl_get_groups_count, + .get_group_name = zynqmp_pctrl_get_group_name, + .get_group_pins = zynqmp_pctrl_get_group_pins, + .dt_node_to_map = pinconf_generic_dt_node_to_map_all, + .dt_free_map = pinctrl_utils_free_map, +}; + +/** + * zynqmp_pinmux_request_pin() - Request a pin for muxing + * @pctldev: Pincontrol device pointer. + * @pin: Pin number. + * + * Request a pin from firmware for muxing. + * + * Return: 0 on success else error code. + */ +static int zynqmp_pinmux_request_pin(struct pinctrl_dev *pctldev, + unsigned int pin) +{ + int ret; + + ret = zynqmp_pm_pinctrl_request(pin); + if (ret) { + dev_err(pctldev->dev, "request failed for pin %u\n", pin); + return -EIO; + } + + return 0; +} + +/** + * zynqmp_pmux_get_functions_count() - get number of functions + * @pctldev: Pincontrol device pointer. + * + * Get total function count. + * + * Return: function count. + */ +static int zynqmp_pmux_get_functions_count(struct pinctrl_dev *pctldev) +{ + struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + return pctrl->nfuncs; +} + +/** + * zynqmp_pmux_get_function_name() - get function name + * @pctldev: Pincontrol device pointer. + * @selector: Function ID. + * + * Get function's name. + * + * Return: function name. + */ +static const char *zynqmp_pmux_get_function_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + return pctrl->funcs[selector].name; +} + +/** + * zynqmp_pmux_get_function_groups() - Get groups for the function + * @pctldev: Pincontrol device pointer. + * @selector: Function ID + * @groups: Group names. + * @num_groups: Number of function groups. + * + * Get function's group count and group names. + * + * Return: Success. + */ +static int zynqmp_pmux_get_function_groups(struct pinctrl_dev *pctldev, + unsigned int selector, + const char * const **groups, + unsigned * const num_groups) +{ + struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + + *groups = pctrl->funcs[selector].groups; + *num_groups = pctrl->funcs[selector].ngroups; + + return 0; +} + +/** + * zynqmp_pinmux_set_mux() - Set requested function for the group + * @pctldev: Pincontrol device pointer. + * @function: Function ID. + * @group: Group ID. + * + * Loop though all pins of group and call firmware API + * to set requested function for all pins in group. + * + * Return: 0 on success else error code. + */ +static int zynqmp_pinmux_set_mux(struct pinctrl_dev *pctldev, + unsigned int function, + unsigned int group) +{ + struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + const struct zynqmp_pctrl_group *pgrp = &pctrl->groups[group]; + int ret, i; + + for (i = 0; i < pgrp->npins; i++) { + unsigned int pin = pgrp->pins[i]; + + ret = zynqmp_pm_pinctrl_set_function(pin, function); + if (ret) { + dev_err(pctldev->dev, "set mux failed for pin %u\n", + pin); + return -EIO; + } + } + + return 0; +} + +/** + * zynqmp_pinmux_release_pin() - Release a pin + * @pctldev: Pincontrol device pointer. + * @pin: Pin number. + * + * Release a pin from firmware. + * + * Return: 0 on success else error code. + */ +static int zynqmp_pinmux_release_pin(struct pinctrl_dev *pctldev, + unsigned int pin) +{ + int ret; + + ret = zynqmp_pm_pinctrl_release(pin); + if (ret) { + dev_err(pctldev->dev, "free pin failed for pin %u\n", + pin); + return -EIO; + } + + return 0; +} + +static const struct pinmux_ops zynqmp_pinmux_ops = { + .request = zynqmp_pinmux_request_pin, + .get_functions_count = zynqmp_pmux_get_functions_count, + .get_function_name = zynqmp_pmux_get_function_name, + .get_function_groups = zynqmp_pmux_get_function_groups, + .set_mux = zynqmp_pinmux_set_mux, + .free = zynqmp_pinmux_release_pin, +}; + +/** + * zynqmp_pinconf_cfg_get() - get config value for the pin + * @pctldev: Pin control device pointer. + * @pin: Pin number. + * @config: Value of config param. + * + * Get value of the requested configuration parameter for the + * given pin. + * + * Return: 0 on success else error code. + */ +static int zynqmp_pinconf_cfg_get(struct pinctrl_dev *pctldev, + unsigned int pin, + unsigned long *config) +{ + int ret; + unsigned int arg = 0, param = pinconf_to_config_param(*config); + + if (pin >= zynqmp_desc.npins) + return -EOPNOTSUPP; + + switch (param) { + case PIN_CONFIG_SLEW_RATE: + param = PM_PINCTRL_CONFIG_SLEW_RATE; + ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); + break; + case PIN_CONFIG_BIAS_PULL_UP: + param = PM_PINCTRL_CONFIG_PULL_CTRL; + ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); + if (arg != PM_PINCTRL_BIAS_PULL_UP) + return -EINVAL; + + arg = 1; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + param = PM_PINCTRL_CONFIG_PULL_CTRL; + ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); + if (arg != PM_PINCTRL_BIAS_PULL_DOWN) + return -EINVAL; + + arg = 1; + break; + case PIN_CONFIG_BIAS_DISABLE: + param = PM_PINCTRL_CONFIG_BIAS_STATUS; + ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); + if (arg != PM_PINCTRL_BIAS_DISABLE) + return -EINVAL; + + arg = 1; + break; + case PIN_CONFIG_IOSTANDARD: + param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS; + ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); + break; + case PIN_CONFIG_INPUT_SCHMITT_ENABLE: + param = PM_PINCTRL_CONFIG_SCHMITT_CMOS; + ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); + break; + case PIN_CONFIG_DRIVE_STRENGTH: + param = PM_PINCTRL_CONFIG_DRIVE_STRENGTH; + ret = zynqmp_pm_pinctrl_get_config(pin, param, &arg); + switch (arg) { + case PM_PINCTRL_DRIVE_STRENGTH_2MA: + arg = DRIVE_STRENGTH_2MA; + break; + case PM_PINCTRL_DRIVE_STRENGTH_4MA: + arg = DRIVE_STRENGTH_4MA; + break; + case PM_PINCTRL_DRIVE_STRENGTH_8MA: + arg = DRIVE_STRENGTH_8MA; + break; + case PM_PINCTRL_DRIVE_STRENGTH_12MA: + arg = DRIVE_STRENGTH_12MA; + break; + default: + /* Invalid drive strength */ + dev_warn(pctldev->dev, + "Invalid drive strength for pin %d\n", + pin); + return -EINVAL; + } + break; + default: + ret = -EOPNOTSUPP; + break; + } + + param = pinconf_to_config_param(*config); + *config = pinconf_to_config_packed(param, arg); + + return ret; +} + +/** + * zynqmp_pinconf_cfg_set() - Set requested config for the pin + * @pctldev: Pincontrol device pointer. + * @pin: Pin number. + * @configs: Configuration to set. + * @num_configs: Number of configurations. + * + * Loop though all configurations and call firmware API + * to set requested configurations for the pin. + * + * Return: 0 on success else error code. + */ +static int zynqmp_pinconf_cfg_set(struct pinctrl_dev *pctldev, + unsigned int pin, unsigned long *configs, + unsigned int num_configs) +{ + int i, ret; + + if (pin >= zynqmp_desc.npins) + return -EOPNOTSUPP; + + for (i = 0; i < num_configs; i++) { + unsigned int param = pinconf_to_config_param(configs[i]); + unsigned int arg = pinconf_to_config_argument(configs[i]); + unsigned int value; + + switch (param) { + case PIN_CONFIG_SLEW_RATE: + param = PM_PINCTRL_CONFIG_SLEW_RATE; + ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); + break; + case PIN_CONFIG_BIAS_PULL_UP: + param = PM_PINCTRL_CONFIG_PULL_CTRL; + arg = PM_PINCTRL_BIAS_PULL_UP; + ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + param = PM_PINCTRL_CONFIG_PULL_CTRL; + arg = PM_PINCTRL_BIAS_PULL_DOWN; + ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); + break; + case PIN_CONFIG_BIAS_DISABLE: + param = PM_PINCTRL_CONFIG_BIAS_STATUS; + arg = PM_PINCTRL_BIAS_DISABLE; + ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); + break; + case PIN_CONFIG_INPUT_SCHMITT_ENABLE: + param = PM_PINCTRL_CONFIG_SCHMITT_CMOS; + ret = zynqmp_pm_pinctrl_set_config(pin, param, arg); + break; + case PIN_CONFIG_DRIVE_STRENGTH: + switch (arg) { + case DRIVE_STRENGTH_2MA: + value = PM_PINCTRL_DRIVE_STRENGTH_2MA; + break; + case DRIVE_STRENGTH_4MA: + value = PM_PINCTRL_DRIVE_STRENGTH_4MA; + break; + case DRIVE_STRENGTH_8MA: + value = PM_PINCTRL_DRIVE_STRENGTH_8MA; + break; + case DRIVE_STRENGTH_12MA: + value = PM_PINCTRL_DRIVE_STRENGTH_12MA; + break; + default: + /* Invalid drive strength */ + dev_warn(pctldev->dev, + "Invalid drive strength for pin %d\n", + pin); + return -EINVAL; + } + + param = PM_PINCTRL_CONFIG_DRIVE_STRENGTH; + ret = zynqmp_pm_pinctrl_set_config(pin, param, value); + break; + case PIN_CONFIG_IOSTANDARD: + param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS; + ret = zynqmp_pm_pinctrl_get_config(pin, param, &value); + + if (arg != value) + dev_warn(pctldev->dev, + "Invalid IO Standard requested for pin %d\n", + pin); + + break; + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: + case PIN_CONFIG_LOW_POWER_MODE: + /* + * These cases are mentioned in dts but configurable + * registers are unknown. So falling through to ignore + * boot time warnings as of now. + */ + ret = 0; + break; + default: + dev_warn(pctldev->dev, + "unsupported configuration parameter '%u'\n", + param); + ret = -EOPNOTSUPP; + break; + } + + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + if (ret) + dev_warn(pctldev->dev, + "%s failed: pin %u param %u value %u\n", + __func__, pin, param, arg); + } + + return 0; +} + +/** + * zynqmp_pinconf_group_set() - Set requested config for the group + * @pctldev: Pincontrol device pointer. + * @selector: Group ID. + * @configs: Configuration to set. + * @num_configs: Number of configurations. + * + * Call function to set configs for each pin in group. + * + * Return: 0 on success else error code. + */ +static int zynqmp_pinconf_group_set(struct pinctrl_dev *pctldev, + unsigned int selector, + unsigned long *configs, + unsigned int num_configs) +{ + int i, ret; + struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + const struct zynqmp_pctrl_group *pgrp = &pctrl->groups[selector]; + + for (i = 0; i < pgrp->npins; i++) { + ret = zynqmp_pinconf_cfg_set(pctldev, pgrp->pins[i], configs, + num_configs); + if (ret) + return ret; + } + + return 0; +} + +static const struct pinconf_ops zynqmp_pinconf_ops = { + .is_generic = true, + .pin_config_get = zynqmp_pinconf_cfg_get, + .pin_config_set = zynqmp_pinconf_cfg_set, + .pin_config_group_set = zynqmp_pinconf_group_set, +}; + +static struct pinctrl_desc zynqmp_desc = { + .name = "zynqmp_pinctrl", + .owner = THIS_MODULE, + .pctlops = &zynqmp_pctrl_ops, + .pmxops = &zynqmp_pinmux_ops, + .confops = &zynqmp_pinconf_ops, +#ifdef CONFIG_DEBUG_FS + .custom_conf_items = zynqmp_conf_items, +#endif +}; + +/** + * zynqmp_pinctrl_get_function_groups() - get groups for the function + * @fid: Function ID. + * @index: Group index. + * @groups: Groups data. + * + * Call firmware API to get groups for the given function. + * + * Return: 0 on success else error code. + */ +static int zynqmp_pinctrl_get_function_groups(u32 fid, u32 index, u16 *groups) +{ + struct zynqmp_pm_query_data qdata = {0}; + u32 ret_payload[PAYLOAD_ARG_CNT]; + int ret; + + qdata.qid = PM_QID_PINCTRL_GET_FUNCTION_GROUPS; + qdata.arg1 = fid; + qdata.arg2 = index; + + ret = zynqmp_pm_query_data(qdata, ret_payload); + if (ret) + return ret; + + memcpy(groups, &ret_payload[1], PINCTRL_GET_FUNC_GROUPS_RESP_LEN); + + return ret; +} + +/** + * zynqmp_pinctrl_get_func_num_groups() - get number of groups in function + * @fid: Function ID. + * @ngroups: Number of groups in function. + * + * Call firmware API to get number of group in function. + * + * Return: 0 on success else error code. + */ +static int zynqmp_pinctrl_get_func_num_groups(u32 fid, unsigned int *ngroups) +{ + struct zynqmp_pm_query_data qdata = {0}; + u32 ret_payload[PAYLOAD_ARG_CNT]; + int ret; + + qdata.qid = PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS; + qdata.arg1 = fid; + + ret = zynqmp_pm_query_data(qdata, ret_payload); + if (ret) + return ret; + + *ngroups = ret_payload[1]; + + return ret; +} + +/** + * zynqmp_pinctrl_prepare_func_groups() - prepare function and groups data + * @dev: Device pointer. + * @fid: Function ID. + * @func: Function data. + * @groups: Groups data. + * + * Query firmware to get group IDs for each function. Firmware returns + * group IDs. Based on gorup index for the function, group names in + * function are stored. For example, first gorup in "eth0" function + * is named as "eth0_0", second as "eth0_1" and so on. + * + * Based on group ID received from firmware, function stores name of + * group for that group ID. For an example, if "eth0" first group ID + * is x, groups[x] name will be stored as "eth0_0". + * + * Once done for each function, each function would have its group names, + * and each groups would also have their names. + * + * Return: 0 on success else error code. + */ +static int zynqmp_pinctrl_prepare_func_groups(struct device *dev, u32 fid, + struct zynqmp_pmux_function *func, + struct zynqmp_pctrl_group *groups) +{ + u16 resp[NUM_GROUPS_PER_RESP] = {0}; + const char **fgroups; + int ret = 0, index, i; + + fgroups = devm_kzalloc(dev, sizeof(*fgroups) * func->ngroups, + GFP_KERNEL); + if (!fgroups) + return -ENOMEM; + + for (index = 0; index < func->ngroups; index += NUM_GROUPS_PER_RESP) { + ret = zynqmp_pinctrl_get_function_groups(fid, index, resp); + if (ret) + return ret; + + for (i = 0; i < NUM_GROUPS_PER_RESP; i++) { + if (resp[i] == (u16)NA_GROUP) + goto done; + + if (resp[i] == (u16)RESERVED_GROUP) + continue; + + fgroups[index + i] = devm_kasprintf(dev, GFP_KERNEL, + "%s_%d_grp", + func->name, + index + i); + groups[resp[i]].name = devm_kasprintf(dev, GFP_KERNEL, + "%s_%d_grp", + func->name, + index + i); + } + } +done: + func->groups = fgroups; + + return ret; +} + +/** + * zynqmp_pinctrl_get_function_name() - get function name + * @fid: Function ID. + * @name: Function name + * + * Call firmware API to get name of given function. + * + * Return: 0 on success else error code. + */ +static int zynqmp_pinctrl_get_function_name(u32 fid, char *name) +{ + struct zynqmp_pm_query_data qdata = {0}; + u32 ret_payload[PAYLOAD_ARG_CNT]; + + qdata.qid = PM_QID_PINCTRL_GET_FUNCTION_NAME; + qdata.arg1 = fid; + + zynqmp_pm_query_data(qdata, ret_payload); + memcpy(name, ret_payload, PINCTRL_GET_FUNC_NAME_RESP_LEN); + + return 0; +} + +/** + * zynqmp_pinctrl_get_num_functions() - get number of supported functions + * @nfuncs: Number of functions. + * + * Call firmware API to get number of functions supported by system/board. + * + * Return: 0 on success else error code. + */ +static int zynqmp_pinctrl_get_num_functions(unsigned int *nfuncs) +{ + struct zynqmp_pm_query_data qdata = {0}; + u32 ret_payload[PAYLOAD_ARG_CNT]; + int ret; + + qdata.qid = PM_QID_PINCTRL_GET_NUM_FUNCTIONS; + + ret = zynqmp_pm_query_data(qdata, ret_payload); + if (ret) + return ret; + + *nfuncs = ret_payload[1]; + + return ret; +} + +/** + * zynqmp_pinctrl_get_pin_groups() - get groups for the pin + * @pin: Pin number. + * @index: Group index. + * @groups: Groups data. + * + * Call firmware API to get groups for the given pin. + * + * Return: 0 on success else error code. + */ +static int zynqmp_pinctrl_get_pin_groups(u32 pin, u32 index, u16 *groups) +{ + struct zynqmp_pm_query_data qdata = {0}; + u32 ret_payload[PAYLOAD_ARG_CNT]; + int ret; + + qdata.qid = PM_QID_PINCTRL_GET_PIN_GROUPS; + qdata.arg1 = pin; + qdata.arg2 = index; + + ret = zynqmp_pm_query_data(qdata, ret_payload); + if (ret) + return ret; + + memcpy(groups, &ret_payload[1], PINCTRL_GET_PIN_GROUPS_RESP_LEN); + + return ret; +} + +/** + * zynqmp_pinctrl_group_add_pin() - add pin to given group + * @group: Group data. + * @pin: Pin number. + * + * Add pin number to respective group's pin array at end and + * increment pin count for the group. + * + * Return: 0 on success else error code. + */ +static void zynqmp_pinctrl_group_add_pin(struct zynqmp_pctrl_group *group, + unsigned int pin) +{ + group->pins[group->npins++] = pin; +} + +/** + * zynqmp_pinctrl_create_pin_groups() - assign pins to respective groups + * @dev: Device pointer. + * @groups: Groups data. + * @pin: Pin number. + * + * Query firmware to get groups available for the given pin. + * Based on firmware response(group IDs for the pin), add + * pin number to respective group's pin array. + * + * Once all pins are queries, each groups would have its number + * of pins and pin numbers data. + * + * Return: 0 on success else error code. + */ +static int zynqmp_pinctrl_create_pin_groups(struct device *dev, + struct zynqmp_pctrl_group *groups, + unsigned int pin) +{ + int ret, i, index = 0; + u16 resp[NUM_GROUPS_PER_RESP] = {0}; + + do { + ret = zynqmp_pinctrl_get_pin_groups(pin, index, resp); + if (ret) + return ret; + + for (i = 0; i < NUM_GROUPS_PER_RESP; i++) { + if (resp[i] == (u16)NA_GROUP) + return ret; + + if (resp[i] == (u16)RESERVED_GROUP) + continue; + + zynqmp_pinctrl_group_add_pin(&groups[resp[i]], pin); + } + index += NUM_GROUPS_PER_RESP; + } while (1); + + return ret; +} + +/** + * zynqmp_pinctrl_prepare_group_pins() - prepare each group's pin data + * @dev: Device pointer. + * @groups: Groups data. + * @ngroups: Number of groups. + * + * Prepare pin number and number of pins data for each pins. + * + * Return: 0 on success else error code. + */ +static int zynqmp_pinctrl_prepare_group_pins(struct device *dev, + struct zynqmp_pctrl_group *groups, + unsigned int ngroups) +{ + unsigned int pin; + int ret = 0; + + for (pin = 0; pin < zynqmp_desc.npins; pin++) { + ret = zynqmp_pinctrl_create_pin_groups(dev, groups, pin); + if (ret) + return ret; + } + + return ret; +} + +/** + * zynqmp_pinctrl_prepare_function_info() - prepare function info + * @dev: Device pointer. + * @pctrl: Pin control driver data. + * + * Query firmware for functions, groups and pin information and + * prepare pin control driver data. + * + * Query number of functions and number of function groups (number + * of groups in given function) to allocate required memory buffers + * for functions and groups. Once buffers are allocated to store + * functions and groups data, query and store required information + * (numbe of groups and group names for each function, number of + * pins and pin numbers for each group). + * + * Return: 0 on success else error code. + */ +static int zynqmp_pinctrl_prepare_function_info(struct device *dev, + struct zynqmp_pinctrl *pctrl) +{ + struct zynqmp_pmux_function *funcs; + struct zynqmp_pctrl_group *groups; + int ret, i; + + ret = zynqmp_pinctrl_get_num_functions(&pctrl->nfuncs); + if (ret) + return ret; + + funcs = devm_kzalloc(dev, sizeof(*funcs) * pctrl->nfuncs, GFP_KERNEL); + if (!funcs) + return -ENOMEM; + + for (i = 0; i < pctrl->nfuncs; i++) { + zynqmp_pinctrl_get_function_name(i, funcs[i].name); + + ret = zynqmp_pinctrl_get_func_num_groups(i, &funcs[i].ngroups); + if (ret) + return ret; + + pctrl->ngroups += funcs[i].ngroups; + } + + groups = devm_kzalloc(dev, sizeof(*groups) * pctrl->ngroups, + GFP_KERNEL); + if (!groups) + return -ENOMEM; + + for (i = 0; i < pctrl->nfuncs; i++) { + ret = zynqmp_pinctrl_prepare_func_groups(dev, i, &funcs[i], + groups); + if (ret) + return ret; + } + + ret = zynqmp_pinctrl_prepare_group_pins(dev, groups, pctrl->ngroups); + if (ret) + return ret; + + pctrl->funcs = funcs; + pctrl->groups = groups; + + return ret; +} + +/** + * zynqmp_pinctrl_get_num_pins() - get number of pins in system + * @npins: Number of pins in system/board. + * + * Call firmware API to get number of pins. + * + * Return: 0 on success else error code. + */ +static int zynqmp_pinctrl_get_num_pins(unsigned int *npins) +{ + struct zynqmp_pm_query_data qdata = {0}; + u32 ret_payload[PAYLOAD_ARG_CNT]; + int ret; + + qdata.qid = PM_QID_PINCTRL_GET_NUM_PINS; + + ret = zynqmp_pm_query_data(qdata, ret_payload); + if (ret) + return ret; + + *npins = ret_payload[1]; + + return ret; +} + +/** + * zynqmp_pinctrl_prepare_pin_desc() - prepare pin description info + * @dev: Device pointer. + * @zynqmp_pins: Pin information. + * @npins: Number of pins. + * + * Query number of pins information from firmware and prepare pin + * description containing pin number and pin name. + * + * Return: 0 on success else error code. + */ +static int zynqmp_pinctrl_prepare_pin_desc(struct device *dev, + const struct pinctrl_pin_desc + **zynqmp_pins, + unsigned int *npins) +{ + struct pinctrl_pin_desc *pins, *pin; + int ret; + int i; + + ret = zynqmp_pinctrl_get_num_pins(npins); + if (ret) + return ret; + + pins = devm_kzalloc(dev, sizeof(*pins) * *npins, GFP_KERNEL); + if (!pins) + return -ENOMEM; + + for (i = 0; i < *npins; i++) { + pin = &pins[i]; + pin->number = i; + pin->name = devm_kasprintf(dev, GFP_KERNEL, "%s%d", + ZYNQMP_PIN_PREFIX, i); + } + + *zynqmp_pins = pins; + + return 0; +} + +static int zynqmp_pinctrl_probe(struct platform_device *pdev) +{ + struct zynqmp_pinctrl *pctrl; + int ret; + + pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL); + if (!pctrl) + return -ENOMEM; + + ret = zynqmp_pinctrl_prepare_pin_desc(&pdev->dev, + &zynqmp_desc.pins, + &zynqmp_desc.npins); + if (ret) { + dev_err(&pdev->dev, "%s() pin desc prepare fail with %d\n", + __func__, ret); + return ret; + } + + ret = zynqmp_pinctrl_prepare_function_info(&pdev->dev, pctrl); + if (ret) { + dev_err(&pdev->dev, "%s() function info prepare fail with %d\n", + __func__, ret); + return ret; + } + + pctrl->pctrl = pinctrl_register(&zynqmp_desc, &pdev->dev, pctrl); + if (IS_ERR(pctrl->pctrl)) { + ret = PTR_ERR(pctrl->pctrl); + return ret; + } + + platform_set_drvdata(pdev, pctrl); + + dev_info(&pdev->dev, "zynqmp pinctrl initialized\n"); + + return ret; +} + +static const struct of_device_id zynqmp_pinctrl_of_match[] = { + { .compatible = "xlnx,zynqmp-pinctrl" }, + { } +}; + +static struct platform_driver zynqmp_pinctrl_driver = { + .driver = { + .name = "zynqmp-pinctrl", + .of_match_table = zynqmp_pinctrl_of_match, + }, + .probe = zynqmp_pinctrl_probe, +}; +builtin_platform_driver(zynqmp_pinctrl_driver);