From patchwork Wed Sep 6 02:40:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 720396 Delivered-To: patch@linaro.org Received: by 2002:adf:d08b:0:b0:31d:da82:a3b4 with SMTP id y11csp2461555wrh; Tue, 5 Sep 2023 19:41:11 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEFNlA7Ziti6ZTN/3YrxjwyqM9dictNhrJngN8baLoS/CUSVKsONL7RqADGFvgd9rb7+zhW X-Received: by 2002:adf:e2c8:0:b0:319:6e71:d1dd with SMTP id d8-20020adfe2c8000000b003196e71d1ddmr1195967wrj.12.1693968071810; Tue, 05 Sep 2023 19:41:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1693968071; cv=none; d=google.com; s=arc-20160816; b=Ciqcg7n/KwZJ493x3pesopPiMplzMJWrbFzMNV1I8S9FodVsAxErn73LQ6AFBJcVwM biJw8B6pMEaZHx1QvE7E3gwQ0Br2p0TnwWGEvYCaFJbqf/DyaFHRW7fe/eP9Rmjyz0Yf 0E4OJhRP+o/YClPNWZxPGg71aBd32x78s6Kp1EMHR1ltB8UE4ltfcHETjq4y/VYnUJq3 VdLLOFDBysxaRsWsZjqEOLJYBVnzUq3iNLNssKfE9UFSDgyWoAKJPSFlR3TBPlLFjCyQ DLd5bZamwPpIwf5C4OzI6/nZ/Wy7V11yNLagf9149vfqkorqWbQzTouALmnbNbOd/DBN nlog== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=efrPIYuVGbqbaZHIcWjhNXthVhwrIIYknB2a7MQG9ew=; fh=Yz321xYbZlOZFLAVVWewQ+h9487s8fAdGcGeu++kLX8=; b=VAIUgMmMvTrhGwcwpT4J1LpAQZJVEp9jwCOHBJkgPb3nX+rCocBRIvRqAabREby06V /WqyecciRPieE/hTqWWkhisGhZI6TiUkoroZ6avaZubyVpk7XKGsqTUKn9E5Rxf/8hKB C4BEjPjwywhLrcKxxS9I77MqB3B7hHdHkITctUWvgJoxFP63YVutPUDNPeroFvTlkWoh o55+iv2Logg5AB2NGo+EszXyRgQrMPqXQq1qfFIkt5OvsFzDq8DdAAW5HGdgs67eQIrm eWKU7EFv5eQjksELyAEsqGKRYYTSqWzLtC54D8m3Lj06D/NsBTTVgK4jmxhx+oYobaQL jSIw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=KlVdTSS1; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id r7-20020a5d6947000000b0031dcd537556si6454866wrw.68.2023.09.05.19.41.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Sep 2023 19:41:11 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=KlVdTSS1; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id D85108667A; Wed, 6 Sep 2023 04:41:04 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="KlVdTSS1"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id D1CD286667; Wed, 6 Sep 2023 04:41:03 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pf1-x435.google.com (mail-pf1-x435.google.com [IPv6:2607:f8b0:4864:20::435]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 1034586591 for ; Wed, 6 Sep 2023 04:41:01 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pf1-x435.google.com with SMTP id d2e1a72fcca58-68cc1b70e05so607869b3a.1 for ; Tue, 05 Sep 2023 19:41:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1693968059; x=1694572859; darn=lists.denx.de; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=efrPIYuVGbqbaZHIcWjhNXthVhwrIIYknB2a7MQG9ew=; b=KlVdTSS1wD7AfajaGrPHv6eEtFUZOqEbv3hHQfbCSlHzbt/a2dV+WQlywAaL5AYgtG JS17RT4XgJhpsUBNXRCc1dniuL4EGnXrqVp+/bnEkuFlsNqj1ZDFxBjkU/kWKJ8AHojv cm+F/DhuS653DJ+vloetcsrTaTuqv7NPnVICe1061xg0WNVZdpTmhXpnv60tCXnL+jX5 NSGCsyZCTF1U6W3x47Lsq0tYaFNku2ZMslAbZ9gt9srG+t4WCleoPRm7Dae6X4+iWOhI D3lhlrecFs8BtVX3+99GOaqaZrrI8cSrpLyyJduI7ixynQ9UsB1PMD1DTHJS8yRrsDAi DJ0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1693968059; x=1694572859; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=efrPIYuVGbqbaZHIcWjhNXthVhwrIIYknB2a7MQG9ew=; b=BPLDg+kvdlXOeD9iDU4lUURgzaJowUffq53UBKyeCfHo1zD0OWdEpDzqFY+7h+SZUq mqRxraTo3J5GNFX//dEHtnHjE+5868hgNarPeHUmBTGrMlPfjaKXkPwO0jMKpXSm66WJ /YtLih5dYPS79CEY4xt2JF6FSVCojqEnsvs+ZSay7RpwDv4Ix0HLfQfUUvb5XdFCnU9u FACmOLBpb4w7HJegEWQ5w6H5yQGVW7NfXoNH6T9AFNjyEFvVT5A4C6UIva3kxGAhfE8Z 1jowlKRh091kpJSo7QFdn6cltpJvi1QCOVeCRZBfwLgZgkjEg7nzVXkpo/EjFZsHsNdC Hcrw== X-Gm-Message-State: AOJu0Yw6a/UI/0QLi9s+iVwtK2aZ5DtZyq04LKl5rVeDIIHgQlp2fQBs kcRfyPp/pbWKy6JNLBCAe/7bNZ3YWeMzhf/+YG9+vg== X-Received: by 2002:a05:6a20:8f15:b0:13d:7aa3:aa6c with SMTP id b21-20020a056a208f1500b0013d7aa3aa6cmr19774235pzk.0.1693968059271; Tue, 05 Sep 2023 19:40:59 -0700 (PDT) Received: from octopus.. ([2400:4050:c3e1:100:8294:a07d:b7e9:4033]) by smtp.gmail.com with ESMTPSA id c5-20020a6566c5000000b0056428865aadsm9145378pgw.82.2023.09.05.19.40.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Sep 2023 19:40:58 -0700 (PDT) From: AKASHI Takahiro To: u-boot@lists.denx.de Cc: etienne.carriere@st.com, michal.simek@amd.com, sjg@chromium.org, linus.walleij@linaro.org, Oleksii_Moisieiev@epam.com, AKASHI Takahiro Subject: [RFC 1/6] firmware: scmi: fix protocol enumeration logic Date: Wed, 6 Sep 2023 11:40:06 +0900 Message-Id: <20230906024011.17488-2-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230906024011.17488-1-takahiro.akashi@linaro.org> References: <20230906024011.17488-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean The original logic in enumerating all the protocols accidentally modifies a *loop* variable, node, at Voltage domain protocol. So subsequent protocol nodes in a device tree won't be detected. Signed-off-by: AKASHI Takahiro --- drivers/firmware/scmi/scmi_agent-uclass.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c index 46a2933d51a4..79584c00a066 100644 --- a/drivers/firmware/scmi/scmi_agent-uclass.c +++ b/drivers/firmware/scmi/scmi_agent-uclass.c @@ -422,8 +422,11 @@ static int scmi_bind_protocols(struct udevice *dev) case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI) && scmi_protocol_is_supported(dev, protocol_id)) { - node = ofnode_find_subnode(node, "regulators"); - if (!ofnode_valid(node)) { + ofnode sub_node; + + sub_node = ofnode_find_subnode(node, + "regulators"); + if (!ofnode_valid(sub_node)) { dev_err(dev, "no regulators node\n"); return -ENXIO; } From patchwork Wed Sep 6 02:40:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 720397 Delivered-To: patch@linaro.org Received: by 2002:adf:d08b:0:b0:31d:da82:a3b4 with SMTP id y11csp2461599wrh; Tue, 5 Sep 2023 19:41:22 -0700 (PDT) X-Google-Smtp-Source: AGHT+IExbedc3IMBeq40005Ri33MeMX0DrA6ewToW8NEVzGDG0o2MXy9eRhBO5cmmOLmbo7GLyor X-Received: by 2002:a1c:7914:0:b0:3fa:934c:8360 with SMTP id l20-20020a1c7914000000b003fa934c8360mr1179064wme.8.1693968082743; Tue, 05 Sep 2023 19:41:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1693968082; cv=none; d=google.com; s=arc-20160816; b=im+7GM/Oshsu8ol5aPtG+AeAonaLwhIigc4dPXvbh95293ikEsOOHMu96bIHeydAKt d3Rq9rBQHUWgjoHryK/x+ac1l1kEe1FCR63O19Xu9BF0lN+dUZ2SHKduJumqHzrTI25M 16F8/6D0lC1eDFufthwL4Mv9FRX8L08/lExAUudtoxdSNsMsLpB+HNsz5BTYv3pPBwRy w6uCwIHf8OfbZFZrtHfqy8Cf94VS7jFMmKszpV4LiYbFDpHywr5lFOG6Z5lf50Cs3jWn 1k0LmWxk3KcK3zeWgcIHU6rG2LDAPl7yPJJ4U7pnQKIaVxRifIs1dweFP1M8F/u4oMxz rHjQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=NZwraZo0t3tnCWHq4TbRwxe/8ErYV/OER8HmEq9/qS4=; fh=Yz321xYbZlOZFLAVVWewQ+h9487s8fAdGcGeu++kLX8=; b=r4SiS9ANGOv7EZsU8SNHdeEE6aS65dKDDS9/QJ6199MCh4m+DLij3MSA2UvIUyP8gI A9NyjRs8ZlFYf+G8nw6Iua4Zt7Jbq1Rafhs6ElzeA7LFSxjvBEy7hA1BbfWJvlHYzxxL G1y6V8DEsrh2w1NzyUZO8MkWHM3ntVGaII7i3Fn4cszKbZ7AXEjyvGVKu7vaLRMw9x5j w8fj+/0Ynb20Thw8xjySbUTvIKXIW1t/ERw8HOj2AgZrBt6ol0dr71ibke/BDWEguLCB DIRFYEmSIhsJg4GS6Cs4oaBFnzEU1BjA+/VswsSQD2ZioC3uD+iRphBS1/ueKOfQcBk5 uW3w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=KCySzshv; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id q18-20020a056000137200b0031ad2ccd187si6592761wrz.247.2023.09.05.19.41.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Sep 2023 19:41:22 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=KCySzshv; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 28B9B8664A; Wed, 6 Sep 2023 04:41:08 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="KCySzshv"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 0C10086590; Wed, 6 Sep 2023 04:41:07 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pf1-x434.google.com (mail-pf1-x434.google.com [IPv6:2607:f8b0:4864:20::434]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 47830865B0 for ; Wed, 6 Sep 2023 04:41:03 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pf1-x434.google.com with SMTP id d2e1a72fcca58-68a32506e90so700508b3a.1 for ; Tue, 05 Sep 2023 19:41:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1693968061; x=1694572861; darn=lists.denx.de; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=NZwraZo0t3tnCWHq4TbRwxe/8ErYV/OER8HmEq9/qS4=; b=KCySzshv02S0Nodf4/vQVUxg5s/8euPmHdbNcvdYLPF+Jbh2rpTCd7OYShtBCZAoUl tofjUoMd3dNjpdZYsdhOJ6oNugBS2EfAsSu+3/IqBMNL22wzemQtBFv5076Clx6NkhMA Oo6mUirrJQrZfmXh8f4AXc5dgOPDwrZw5ytTlN/TAtqqWkqF9Bhknyvi/lIXC7VgjjAj o0ibJeSihHnxYj9l2v5VYYhUPkcbH9m5eiqoxA1edIe1Z3tbSXR2UmV1rbXCRlZ2T1fv FRVP7IiGkxJWEZFXtR1JtZO+tda8I9VfVJk5+AivQmqg4zXQQzWbYsOUvYxf4gMH6FbY PhBw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1693968061; x=1694572861; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NZwraZo0t3tnCWHq4TbRwxe/8ErYV/OER8HmEq9/qS4=; b=Fi7QY7TF8s6FfDY7kHK6s2Z+UtV14JTGdhy1xrCOEfy5AEbkJaXG9ZpZs8A6PIsO3m 6i55XpGSjvs6BAOwxApNuC+ah3iwPuub4vxuwHwbWrNrXaJLvwwzz/r0eDCuO0tuXrGV WgWmpXKpJ+x9k5lhZz0a3v+LjgX1hrkSNA0ol1wTOjbjMDCihQ8bGWfqPGMvectitrob b1SFcig+QzxckoWqgqzv8u/2WTZ5KcwPyzZc4r1u15YW7weLoiRZ+282rccyxWkh2qu2 /fhije6aub6ryN8UTeRL5qg9xACfUW07FL96PYeRBJBnCAnSdAXMuYKaGVZbYL0wYdoQ O4/A== X-Gm-Message-State: AOJu0YyvdcrZl9jhPlJwv8XosCUnwZn5Sc/ylAs3b9O9UWrRUw9apOeF /ZEONCnwJJexSrxOQsW//IT/KRKr/EC7lzwuVT8WHA== X-Received: by 2002:a05:6a00:f0e:b0:68b:c562:da46 with SMTP id cr14-20020a056a000f0e00b0068bc562da46mr16015314pfb.1.1693968061405; Tue, 05 Sep 2023 19:41:01 -0700 (PDT) Received: from octopus.. ([2400:4050:c3e1:100:8294:a07d:b7e9:4033]) by smtp.gmail.com with ESMTPSA id c5-20020a6566c5000000b0056428865aadsm9145378pgw.82.2023.09.05.19.40.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Sep 2023 19:41:01 -0700 (PDT) From: AKASHI Takahiro To: u-boot@lists.denx.de Cc: etienne.carriere@st.com, michal.simek@amd.com, sjg@chromium.org, linus.walleij@linaro.org, Oleksii_Moisieiev@epam.com, AKASHI Takahiro Subject: [RFC 2/6] firmware: scmi: add pinctrl protocol support Date: Wed, 6 Sep 2023 11:40:07 +0900 Message-Id: <20230906024011.17488-3-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230906024011.17488-1-takahiro.akashi@linaro.org> References: <20230906024011.17488-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean With this patch, transport-level utility functions for SCMI pinctrl protocol are added. DM-compliant device drivers, pinctrl and gpio, are added in the following patches. Signed-off-by: AKASHI Takahiro --- cmd/scmi.c | 1 + drivers/firmware/scmi/Kconfig | 3 + drivers/firmware/scmi/Makefile | 1 + drivers/firmware/scmi/pinctrl.c | 412 ++++++++++++++++++++ drivers/firmware/scmi/scmi_agent-uclass.c | 11 + include/scmi_agent-uclass.h | 2 + include/scmi_protocols.h | 435 ++++++++++++++++++++++ 7 files changed, 865 insertions(+) create mode 100644 drivers/firmware/scmi/pinctrl.c diff --git a/cmd/scmi.c b/cmd/scmi.c index 5efec8ad87fd..ae7892381e0a 100644 --- a/cmd/scmi.c +++ b/cmd/scmi.c @@ -33,6 +33,7 @@ struct { {SCMI_PROTOCOL_ID_SENSOR, "Sensor management"}, {SCMI_PROTOCOL_ID_RESET_DOMAIN, "Reset domain management"}, {SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN, "Voltage domain management"}, + {SCMI_PROTOCOL_ID_PIN_CONTROL, "Pin control"}, }; /** diff --git a/drivers/firmware/scmi/Kconfig b/drivers/firmware/scmi/Kconfig index 8cf85f0d7a12..e0cb7b70dede 100644 --- a/drivers/firmware/scmi/Kconfig +++ b/drivers/firmware/scmi/Kconfig @@ -41,3 +41,6 @@ config SCMI_AGENT_OPTEE help Enable the SCMI communication channel based on OP-TEE transport for compatible "linaro,scmi-optee". + +config SCMI_PINCTRL + bool diff --git a/drivers/firmware/scmi/Makefile b/drivers/firmware/scmi/Makefile index 1a23d4981709..bf6381332e9e 100644 --- a/drivers/firmware/scmi/Makefile +++ b/drivers/firmware/scmi/Makefile @@ -4,4 +4,5 @@ obj-y += smt.o obj-$(CONFIG_SCMI_AGENT_SMCCC) += smccc_agent.o obj-$(CONFIG_SCMI_AGENT_MAILBOX) += mailbox_agent.o obj-$(CONFIG_SCMI_AGENT_OPTEE) += optee_agent.o +obj-$(CONFIG_SCMI_PINCTRL) += pinctrl.o obj-$(CONFIG_SANDBOX) += sandbox-scmi_agent.o sandbox-scmi_devices.o diff --git a/drivers/firmware/scmi/pinctrl.c b/drivers/firmware/scmi/pinctrl.c new file mode 100644 index 000000000000..88ec57dc3d53 --- /dev/null +++ b/drivers/firmware/scmi/pinctrl.c @@ -0,0 +1,412 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * SCMI Pin control protocol as U-Boot device + * + * Copyright (C) 2023 Linaro Limited + * author: AKASHI Takahiro + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * struct scmi_pinctrl_priv - Private data for SCMI Pin control protocol + * @channel: Reference to the SCMI channel to use + */ +struct scmi_pinctrl_priv { + struct scmi_channel *channel; +}; + +int scmi_pinctrl_protocol_attrs(struct udevice *dev, u32 *num_pins, + u32 *num_groups, u32 *num_functions) +{ + struct scmi_pinctrl_protocol_attrs_out out; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_PIN_CONTROL, + .message_id = SCMI_PROTOCOL_ATTRIBUTES, + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + int ret; + + if (!dev || !num_pins || !num_groups || !num_functions) + return -EINVAL; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (out.status) + return scmi_to_linux_errno(out.status); + + *num_groups = SCMI_PINCTRL_ATTRS_NUM_GROUPS(out.attributes_low); + *num_pins = SCMI_PINCTRL_ATTRS_NUM_PINS(out.attributes_low); + *num_functions = SCMI_PINCTRL_ATTRS_NUM_FUNCTIONS(out.attributes_high); + + return 0; +} + +int scmi_pinctrl_attrs(struct udevice *dev, u32 id, u32 flags, + bool *extended_name, u8 **name) +{ + struct scmi_pinctrl_attrs_in in; + struct scmi_pinctrl_attrs_out out; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_PIN_CONTROL, + .message_id = SCMI_PINCTRL_ATTRIBUTES, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + int ret; + + if (!dev || !extended_name || !name) + return -EINVAL; + + in.id = id; + in.flags = flags; + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (out.status) + return scmi_to_linux_errno(out.status); + + *extended_name = SCMI_PINCTRL_ATTRS_EXTENDED_NAME(out.attributes); + *name = strdup(out.name); + if (!*name) + return -ENOMEM; + + return 0; +} + +int scmi_pinctrl_list_assocs(struct udevice *dev, u32 id, u32 flags, + u16 **array) +{ + struct scmi_pinctrl_list_assocs_in in; + struct scmi_pinctrl_list_assocs_out out; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_PIN_CONTROL, + .message_id = SCMI_PINCTRL_LIST_ASSOCIATIONS, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + u32 index; + u16 *buf; + int i, ret; + + if (!dev || !array) + return -EINVAL; + + in.id = id; + in.flags = flags; + + buf = calloc(sizeof(u16), SCMI_PINCTRL_ARRAY_SIZE); + if (!buf) + return -ENOMEM; + + index = 0; + while (1) { + in.index = index; + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + goto err; + if (out.status) { + ret = scmi_to_linux_errno(out.status); + goto err; + } + + for (i = 0; i < SCMI_PINCTRL_LIST_NUM_PINGROUP(out.flags); + i++, index++) + buf[index] = out.array[i]; + + /* realloc should happen only once */ + if (SCMI_PINCTRL_LIST_NUM_REMAINING(out.flags)) { + buf = realloc(buf, sizeof(u16) * + (SCMI_PINCTRL_ARRAY_SIZE + + SCMI_PINCTRL_LIST_NUM_REMAINING(out.flags))); + if (!buf) + return -ENOMEM; + } else { + break; + } + } + + *array = buf; + + return index; +err: + free(buf); + + return ret; +} + +int scmi_pinctrl_config_get(struct udevice *dev, u32 id, bool all_configs, + int selector, unsigned int config_type, + struct scmi_pin_entry **configs) + +{ + struct scmi_pinctrl_config_get_in in; + struct scmi_pinctrl_config_get_out out; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_PIN_CONTROL, + .message_id = SCMI_PINCTRL_CONFIG_GET, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + struct scmi_pin_entry *entry; + int cur, num, remaining, ret; + + if (!dev) + return -EINVAL; + + if (!all_configs) { + in.id = id; + in.attributes = SCMI_PINCTRL_CONFIG_GET_ATTRS(0, selector, 0, + config_type); + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (out.status) + return scmi_to_linux_errno(out.status); + + entry = malloc(sizeof(*entry)); + if (!entry) + return -ENOMEM; + + *entry = out.configs[0]; + *configs = entry; + + return 0; + } + + entry = NULL; + cur = 0; + while (1) { + in.id = id; + in.attributes = SCMI_PINCTRL_CONFIG_GET_ATTRS(1, selector, cur, + 0); + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (out.status) + return scmi_to_linux_errno(out.status); + + num = SCMI_PINCTRL_CONFIG_GET_NUM_RET(out.num_configs); + remaining = SCMI_PINCTRL_CONFIG_GET_REMAINING(out.num_configs); + + if (!entry) + entry = malloc(sizeof(*entry) * (num + remaining)); + if (!entry) + return -ENOMEM; + + memcpy(entry + cur, &out.configs, sizeof(*entry) * num); + + if (!remaining) + break; + + cur += num; + } + + return 0; +} + +int scmi_pinctrl_config_set(struct udevice *dev, u32 id, int selector, + int num_configs, struct scmi_pin_entry *configs) +{ + s32 status; + struct scmi_pinctrl_config_set_in in; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_PIN_CONTROL, + .message_id = SCMI_PINCTRL_CONFIG_SET, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&status, + .out_msg_sz = sizeof(status), + }; + int cur, num, ret; + + if (!dev) + return -EINVAL; + + cur = 0; + while (num_configs) { + if (num_configs < SCMI_PINCTRL_CONFIG_ENTRY_MAX) + num = num_configs; + else + num = SCMI_PINCTRL_CONFIG_ENTRY_MAX; + + in.id = id; + in.attributes = SCMI_PINCTRL_CONFIG_SET_ATTRS(num, selector); + memcpy(&in.configs[cur], configs, + sizeof(struct scmi_pin_entry) * num); + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (status) + return scmi_to_linux_errno(status); + + num_configs -= num; + cur += num; + } + + return 0; +} + +int scmi_pinctrl_function_select(struct udevice *dev, u32 id, u32 function_id, + u32 flags) +{ + s32 status; + struct scmi_pinctrl_function_select_in in; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_PIN_CONTROL, + .message_id = SCMI_PINCTRL_FUNCTION_SELECT, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&status, + .out_msg_sz = sizeof(status), + }; + int ret; + + if (!dev) + return -EINVAL; + + in.id = id; + in.function_id = function_id; + in.flags = flags; + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (status) + return scmi_to_linux_errno(status); + + return 0; +} + +int scmi_pinctrl_request(struct udevice *dev, u32 id, u32 flags) +{ + s32 status; + struct scmi_pinctrl_request_in in; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_PIN_CONTROL, + .message_id = SCMI_PINCTRL_REQUEST, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&status, + .out_msg_sz = sizeof(status), + }; + int ret; + + if (!dev) + return -EINVAL; + + in.id = id; + in.flags = flags; + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (status) + return scmi_to_linux_errno(status); + + return 0; +} + +int scmi_pinctrl_release(struct udevice *dev, u32 id, u32 flags) +{ + s32 status; + struct scmi_pinctrl_release_in in; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_PIN_CONTROL, + .message_id = SCMI_PINCTRL_RELEASE, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&status, + .out_msg_sz = sizeof(status), + }; + int ret; + + if (!dev) + return -EINVAL; + + in.id = id; + in.flags = flags; + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (status) + return scmi_to_linux_errno(status); + + return 0; +} + +int scmi_pinctrl_name_get(struct udevice *dev, u32 id, u32 flags, u8 **name) +{ + struct scmi_pinctrl_name_get_in in; + struct scmi_pinctrl_name_get_out out; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_PIN_CONTROL, + .message_id = SCMI_PINCTRL_NAME_GET, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + int ret; + + if (!dev || !name) + return -EINVAL; + + in.id = id; + in.flags = flags; + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (out.status) + return scmi_to_linux_errno(out.status); + + *name = strdup(out.name); + if (!*name) + return -ENOMEM; + + return 0; +} + +int scmi_pinctrl_set_permissions(struct udevice *dev, u32 agent_id, u32 id, + u32 flags) +{ + s32 status; + struct scmi_pinctrl_set_permissions_in in; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_PIN_CONTROL, + .message_id = SCMI_PINCTRL_SET_PERMISSIONS, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&status, + .out_msg_sz = sizeof(status), + }; + int ret; + + if (!dev) + return -EINVAL; + + in.agent_id = agent_id; + in.id = id; + in.flags = flags; + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + if (status) + return scmi_to_linux_errno(status); + + return 0; +} diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c index 79584c00a066..a5953cabbcee 100644 --- a/drivers/firmware/scmi/scmi_agent-uclass.c +++ b/drivers/firmware/scmi/scmi_agent-uclass.c @@ -95,6 +95,9 @@ struct udevice *scmi_get_protocol(struct udevice *dev, case SCMI_PROTOCOL_ID_CLOCK: proto = priv->clock_dev; break; + case SCMI_PROTOCOL_ID_PIN_CONTROL: + proto = priv->pinctrl_dev; + break; case SCMI_PROTOCOL_ID_RESET_DOMAIN: proto = priv->resetdom_dev; break; @@ -142,6 +145,9 @@ static int scmi_add_protocol(struct udevice *dev, case SCMI_PROTOCOL_ID_CLOCK: priv->clock_dev = proto; break; + case SCMI_PROTOCOL_ID_PIN_CONTROL: + priv->pinctrl_dev = proto; + break; case SCMI_PROTOCOL_ID_RESET_DOMAIN: priv->resetdom_dev = proto; break; @@ -414,6 +420,11 @@ static int scmi_bind_protocols(struct udevice *dev) scmi_protocol_is_supported(dev, protocol_id)) drv = DM_DRIVER_GET(scmi_clock); break; + case SCMI_PROTOCOL_ID_PIN_CONTROL: + if (IS_ENABLED(CONFIG_PINCTRL_SCMI) && + scmi_protocol_is_supported(dev, protocol_id)) + drv = DM_DRIVER_GET(scmi_pinctrl); + break; case SCMI_PROTOCOL_ID_RESET_DOMAIN: if (IS_ENABLED(CONFIG_RESET_SCMI) && scmi_protocol_is_supported(dev, protocol_id)) diff --git a/include/scmi_agent-uclass.h b/include/scmi_agent-uclass.h index 6fd6d54d6a5a..993ea81e09c8 100644 --- a/include/scmi_agent-uclass.h +++ b/include/scmi_agent-uclass.h @@ -25,6 +25,7 @@ struct scmi_channel; * @base_dev: SCMI base protocol device * @clock_dev: SCMI clock protocol device * @resetdom_dev: SCMI reset domain protocol device + * @pinctrl_dev: SCMI pin control protocol device * @voltagedom_dev: SCMI voltage domain protocol device */ struct scmi_agent_priv { @@ -40,6 +41,7 @@ struct scmi_agent_priv { struct udevice *base_dev; struct udevice *clock_dev; struct udevice *resetdom_dev; + struct udevice *pinctrl_dev; struct udevice *voltagedom_dev; }; diff --git a/include/scmi_protocols.h b/include/scmi_protocols.h index f41d3f317ce2..699e27e0a84f 100644 --- a/include/scmi_protocols.h +++ b/include/scmi_protocols.h @@ -24,6 +24,7 @@ enum scmi_std_protocol { SCMI_PROTOCOL_ID_SENSOR = 0x15, SCMI_PROTOCOL_ID_RESET_DOMAIN = 0x16, SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN = 0x17, + SCMI_PROTOCOL_ID_PIN_CONTROL = 0x19, }; enum scmi_status_code { @@ -683,4 +684,438 @@ struct scmi_voltd_level_get_out { s32 voltage_level; }; +/* + * SCMI Pin Control Protocol + */ +#define SCMI_PIN_CONTROL_PROTOCOL_VERSION 0x10000 + +enum scmi_pin_control_id { + SCMI_PINCTRL_ATTRIBUTES = 0x3, + SCMI_PINCTRL_LIST_ASSOCIATIONS = 0x4, + SCMI_PINCTRL_CONFIG_GET = 0x5, + SCMI_PINCTRL_CONFIG_SET = 0x6, + SCMI_PINCTRL_FUNCTION_SELECT = 0x7, + SCMI_PINCTRL_REQUEST = 0x8, + SCMI_PINCTRL_RELEASE = 0x9, + SCMI_PINCTRL_NAME_GET = 0xa, + SCMI_PINCTRL_SET_PERMISSIONS = 0xb, +}; + +#define SCMI_PINCTRL_NAME_LENGTH_MAX 16 + +/** + * struct scmi_pinctrl_protocol_attrs_out - Response for PINCTRL's + * PROTOCOL_ATTRIBUTES command + * @status: SCMI command status + * @attributes_low: Protocol attributes (lower bytes) + * @attributes_high: Protocol attributes (higher bytes) + */ +struct scmi_pinctrl_protocol_attrs_out { + s32 status; + u32 attributes_low; + u32 attributes_high; +}; + +#define SCMI_PINCTRL_ATTRS_NUM_GROUPS(attributes_low) \ + (((attributes_low) & GENMASK(31, 16)) >> 16) +#define SCMI_PINCTRL_ATTRS_NUM_PINS(attributes_low) \ + ((attributes_low) & GENMASK(15, 0)) +#define SCMI_PINCTRL_ATTRS_NUM_FUNCTIONS(attributes_high) \ + ((attributes_high) & GENMASK(15, 0)) + +/** + * struct scmi_pinctrl_attrs_in - Message payload for + * SCMI_PINCTRL_ATTRIBUTES command + * @id: Identifier of pin, group or function + * @flags: A set of flags + */ +struct scmi_pinctrl_attrs_in { + u32 id; + u32 flags; +}; + +/** + * struct scmi_pinctrl_attrs_out - Response payload for + * SCMI_PINCTRL_ATTRIBUTES command + * @status: SCMI command status + * @attributes: Attributes of pin, group for function + * @name: Name of pin, group or function + */ +struct scmi_pinctrl_attrs_out { + u32 status; + u32 attributes; + u8 name[SCMI_PINCTRL_NAME_LENGTH_MAX]; +}; + +#define SCMI_PINCTRL_TYPE(flags) ((flags) & GENMASK(1, 0)) +#define SCMI_PINCTRL_TYPE_PIN 0x0 +#define SCMI_PINCTRL_TYPE_GROUP 0x1 +#define SCMI_PINCTRL_TYPE_FUNCTION 0x2 + +#define SCMI_PINCTRL_ATTRS_EXTENDED_NAME(attributes) \ + ((attributes) & BIT(31)) +#define SCMI_PINCTRL_ATTRS_NUM_PINGROUP(attributes) \ + ((attributes) & GENMASK(15, 0)) + +/** + * struct scmi_pinctrl_list_assocs_in - Message payload for + * SCMI_PINCTRL_LIST_ASSOCIATIONS command + * @id: Identifier of group or function + * @flags: A set of flags + * @index: Index of first group to be described + */ +struct scmi_pinctrl_list_assocs_in { + u32 id; + u32 flags; + u32 index; +}; + +#define SCMI_PINCTRL_ARRAY_SIZE 8 + +/** + * struct scmi_pinctrl_list_assocs_out - Response payload for + * SCMI_PINCTRL_LIST_ASSOCIATIONS command + * @status: SCMI command status + * @attributes: A set of flags + * @array: Array of pin or group identifiers + */ +struct scmi_pinctrl_list_assocs_out { + u32 status; + u32 flags; + u16 array[SCMI_PINCTRL_ARRAY_SIZE]; +}; + +#define SCMI_PINCTRL_LIST_NUM_REMAINING(flags) \ + (((flags) & GENMASK(31, 16)) >> 16) +#define SCMI_PINCTRL_LIST_NUM_PINGROUP(flags) \ + ((flags) & GENMASK(11, 0)) + +/* FIXME: depends on transport */ +#define SCMI_PINCTRL_CONFIG_ENTRY_MAX 8 + +struct scmi_pin_entry { + u32 type; + u32 value; +}; + +/** + * struct scmi_pinctrl_config_get_in - Message payload for + * SCMI_PINCTRL_CONFIG_GET command + * @id: Identifier of pin or group + * @attributes: Configuration attributes + */ +struct scmi_pinctrl_config_get_in { + u32 id; + u32 attributes; +}; + +#define SCMI_PINCTRL_CONFIG_GET_ATTRS(all, selector, skip, type) \ + (((all) << 18) | ((selector) << 16) | \ + (((skip) << 8) | (type))) + +#define SCMI_PINCTRL_CONFIG_GET_ALL BIT(18) +#define SCMI_PINCTRL_CONFIG_GET_PINCTRL_TYPE(attributes) \ + (((attributes) & GENMASK(17, 16)) >> 16) +#define SCMI_PINCTRL_CONFIG_GET_SKIP(attributes) \ + (((attributes) & GENMASK(15, 8)) >> 8) +#define SCMI_PINCTRL_CONFIG_GET_TYPE(attributes) \ + ((attributes) & GENMASK(7, 0)) + +/** + * struct scmi_pinctrl_confige_get_out - Response payload for + * SCMI_PINCTRL_CONFIG_GET command + * @status: SCMI command status + * @num_configs: Number of configuration types + * @configs: Values of configuration types + */ +struct scmi_pinctrl_config_get_out { + u32 status; + u32 num_configs; + struct scmi_pin_entry configs[SCMI_PINCTRL_CONFIG_ENTRY_MAX]; +}; + +#define SCMI_PINCTRL_CONFIG_GET_REMAINING(attributes) \ + (((attributes) & GENMASK(31, 24)) >> 24) +#define SCMI_PINCTRL_CONFIG_GET_NUM_RET(attributes) \ + ((attributes) & GENMASK(7, 0)) +#define SCMI_PINCTRL_CONFIG_GET_NUM_CONFIGS(remaining, num) \ + (((remaining) << 24) | (num)) + +#define SCMI_PINCTRL_CONFIG_ID_SHIFT 8 + +#define SCMI_PINCTRL_CONFIG_DEFAULT 0 +#define SCMI_PINCTRL_CONFIG_BIAS_BUS_HOLD 1 +#define SCMI_PINCTRL_CONFIG_BIAS_DISABLE 2 +#define SCMI_PINCTRL_CONFIG_BIAS_HI_IMPEDANCE 3 +#define SCMI_PINCTRL_CONFIG_BIAS_PULL_UP 4 +#define SCMI_PINCTRL_CONFIG_BIAS_PULL_DEF 5 +#define SCMI_PINCTRL_CONFIG_BIAS_PULL_DOWN 6 +#define SCMI_PINCTRL_CONFIG_DRIVE_OPEN_DRAIN 7 +#define SCMI_PINCTRL_CONFIG_DRIVE_OPEN_SOURCE 8 +#define SCMI_PINCTRL_CONFIG_DRIVE_PUSH_PULL 9 +#define SCMI_PINCTRL_CONFIG_DRIVE_STRENGTH 10 +#define SCMI_PINCTRL_CONFIG_INPUT_DEBOUNCE 11 +#define SCMI_PINCTRL_CONFIG_INPUT_MODE 12 +#define SCMI_PINCTRL_CONFIG_PULL_MODE 13 +#define SCMI_PINCTRL_CONFIG_INPUT_VALUE 14 +#define SCMI_PINCTRL_CONFIG_INPUT_SCHMITT 15 +#define SCMI_PINCTRL_CONFIG_LOW_POWER_MODE 16 +#define SCMI_PINCTRL_CONFIG_OUTPUT_MODE 17 +#define SCMI_PINCTRL_CONFIG_OUTPUT_VALUE 18 +#define SCMI_PINCTRL_CONFIG_POWER_SOURCE 19 +#define SCMI_PINCTRL_CONFIG_SLEW_RATE 20 +#define SCMI_PINCTRL_CONFIG_RESERVED 21 +#define SCMI_PINCTRL_CONFIG_OEM 192 + +/** + * struct scmi_pinctrl_config_set_in - Message payload for + * SCMI_PINCTRL_CONFIG_GET command + * @id: Identifier of pin or group + * @attributes: Configuration attributes + * @configs: Values of configuration types + */ +struct scmi_pinctrl_config_set_in { + u32 id; + u32 attributes; + struct scmi_pin_entry configs[SCMI_PINCTRL_CONFIG_ENTRY_MAX]; +}; + +#define SCMI_PINCTRL_CONFIG_SET_ATTRS(num, type) \ + (((num) << 2) | (type)) +#define SCMI_PINCTRL_CONFIG_SET_NUM_CONFIGS(attributes) \ + (((attributes) & GENMASK(9, 2)) >> 2) +#define SCMI_PINCTRL_CONFIG_SET_PINCTRL_TYPE(attributes) \ + ((attributes) & GENMASK(1, 0)) + +/** + * struct scmi_pinctrl_function_select_in - Message payload for + * SCMI_PINCTRL_FUNCTION_SELECT command + * @id: Identifier of pin or group + * @function_id: Identifier of function + * @flags: A set of flags + */ +struct scmi_pinctrl_function_select_in { + u32 id; + u32 function_id; + u32 flags; +}; + +/** + * struct scmi_pinctrl_request_in - Message payload for + * SCMI_PINCTRL_REQUEST command + * @id: Identifier of pin or group + * @flags: A set of flags + */ +struct scmi_pinctrl_request_in { + u32 id; + u32 flags; +}; + +/** + * struct scmi_pinctrl_release_in - Message payload for + * SCMI_PINCTRL_RELEASE command + * @id: Identifier of pin or group + * @flags: A set of flags + */ +struct scmi_pinctrl_release_in { + u32 id; + u32 flags; +}; + +/** + * struct scmi_pinctrl_name_get_in - Message payload for + * SCMI_PINCTRL_NAME_GET command + * @id: Identifier of pin, group or function + * @flags: A set of flags + */ +struct scmi_pinctrl_name_get_in { + u32 id; + u32 flags; +}; + +/** + * struct scmi_pinctrl_name_get_out - Response payload for + * SCMI_PINCTRL_NAME_GET command + * @status: SCMI command status + * @flags: A set of flags (reserved) + * @name: Name in string + */ +struct scmi_pinctrl_name_get_out { + u32 status; + u32 flags; + u8 name[64]; +}; + +/** + * struct scmi_pinctrl_set_permissions_in - Message payload for + * SCMI_PINCTRL_SET_PERMISSIONS command + * @agent_id: Identifier of the agent + * @id: Identifier of pin or group + * @flags: A set of flags + */ +struct scmi_pinctrl_set_permissions_in { + u32 agent_id; + u32 id; + u32 flags; +}; + +#define SCMI_PINCTRL_PERMISSION BIT(2) + +/** + * scmi_pinctrl_protocol_attrs - get attributes of pinctrl protocol + * @dev: SCMI pinctrl device + * @num_pins: A number of pins + * @num_groups: A number of groups + * @num_functions: A number of functions + * + * Get a number of available pins, groups and functions, respectively, + * in @num_pins, @num_groups, @num_functions. + * + * Return: 0 on success, error code otherwise + */ +int scmi_pinctrl_protocol_attrs(struct udevice *dev, u32 *num_pins, + u32 *num_groups, u32 *num_functions); + +/** + * scmi_pinctrl_attrs - get attributes of pin, group or function + * @dev: SCMI pinctrl device + * @id: Identifier of pin, group or function + * @flags: A set of flags + * @extended_name: Bit flag for extended name + * @name: Name of pin, group or function + * + * Get the name of @id in @name. + * @flags can be SCMI_PINCTRL_TYPE_PIN, GROUP or FUNCTION. + * If @id has an extended name, @extended_name is set to true. + * + * Return: 0 on success, error code otherwise + */ +int scmi_pinctrl_attrs(struct udevice *dev, u32 id, u32 flags, + bool *extended_name, u8 **name); + +/** + * scmi_pinctrl_list_assocs - Get a list of pins or groups + * @dev: SCMI pinctrl device + * @id: Identifier of group or function + * @flags: A set of flags + * @array: A pointer to a list of pins, groups or functions + * + * Get a list of pins or groups associated with @id in @array. + * @flags can be SCMI_PINCTRL_TYPE_GROUP or FUNCTION. + * + * Return: 0 on success, error code otherwise + */ +int scmi_pinctrl_list_assocs(struct udevice *dev, u32 id, u32 flags, + u16 **array); + +/** + * scmi_pinctrl_config_get - Get configuration + * @dev: SCMI pinctrl device + * @id: Identifier of pin or group + * @all_configs: Identifier of pin or group + * @selector: Type of id + * @config_type: Type of configuration + * @configs: A pointer to an array of configuration data + * + * If @all_configs is set, get a list of values of all configuration types + * associated with @id in @configs, otherwise get the configuration for + * a specific @config_type. Each configuration data is presented in a form + * of struct scmi_pin_entry. + * @selector can be SCMI_PINCTRL_TYPE_PIN or GROUP. + * + * Return: 0 on success, error code otherwise + */ +int scmi_pinctrl_config_get(struct udevice *dev, u32 id, bool all_configs, + int selector, unsigned int config_type, + struct scmi_pin_entry **configs); + +/** + * scmi_pinctrl_config_set - Set configuration + * @dev: SCMI pinctrl device + * @id: Identifier of pin or group + * @selector: Type of id + * @num_configs: A number of configuration data + * @configs: A pointer to an array of configuration data + * + * Configure a pin or group associated with @id using @configs. + * Each configuration data is presented in a form of struct scmi_pin_entry. + * @selector can be SCMI_PINCTRL_TYPE_PIN or GROUP. + * + * Return: 0 on success, error code otherwise + */ +int scmi_pinctrl_config_set(struct udevice *dev, u32 id, int selector, + int num_configs, struct scmi_pin_entry *configs); + +/** + * scmi_pinctrl_function_select - Select a function + * @dev: SCMI pinctrl device + * @id: Identifier of pin or group + * @function_id: Identifier of function + * @flags: A set of flags + * + * Select a function, @function_id, for a pin or group with @id. + * @flags can be SCMI_PINCTRL_TYPE_PIN or GROUP. + * + * Return: 0 on success, error code otherwise + */ +int scmi_pinctrl_function_select(struct udevice *dev, u32 id, u32 function_id, + u32 flags); + +/** + * scmi_pinctrl_request - Request exclusive control + * @dev: SCMI pinctrl device + * @id: Identifier of pin or group + * @flags: A set of flags + * + * Make a request for exclusive control of pin or group with @id by this agent. + * Once granted, no other agent can access @id until released. + * @flags can be SCMI_PINCTRL_TYPE_PIN or GROUP. + * + * Return: 0 on success, error code otherwise + */ +int scmi_pinctrl_request(struct udevice *dev, u32 id, u32 flags); + +/** + * scmi_pinctrl_release - Release exclusive control + * @dev: SCMI pinctrl device + * @id: Identifier of pin or group + * @flags: A set of flags + * + * Release exclusive control of pin or group with @id by this agent. + * @flags can be SCMI_PINCTRL_TYPE_PIN or GROUP. + * + * Return: 0 on success, error code otherwise + */ +int scmi_pinctrl_release(struct udevice *dev, u32 id, u32 flags); + +/** + * scmi_pinctrl_name_get - Get extended name + * @dev: SCMI pinctrl device + * @id: Identifier of pin, group or function + * @flags: A set of flags + * + * Get an extended name of pin, group or function with @id. + * @flags can be SCMI_PINCTRL_TYPE_PIN, GROUP or FUNCTION. + * + * Return: 0 on success, error code otherwise + */ +int scmi_pinctrl_name_get(struct udevice *dev, u32 id, u32 flags, u8 **name); + +/** + * scmi_pinctrl_set_permissions - Claim access permission + * @dev: SCMI pinctrl device + * @agent_id: Identifier of SCMI agent + * @id: Identifier of pin or group + * @flags: A set of flags + * + * Request to set or deny access permission against @id for the agent + * with @agent_id. + * Bit[2] of @flags indicates "allow access" if set, otherwise "deny access". + * @flags should have SCMI_PINCTRL_TYPE_PIN or GROUP. + * + * Return: 0 on success, error code otherwise + */ +int scmi_pinctrl_set_permissions(struct udevice *dev, u32 agent_id, u32 id, + u32 flags); + #endif /* _SCMI_PROTOCOLS_H */ From patchwork Wed Sep 6 02:40:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 720398 Delivered-To: patch@linaro.org Received: by 2002:adf:d08b:0:b0:31d:da82:a3b4 with SMTP id y11csp2461633wrh; Tue, 5 Sep 2023 19:41:34 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFebaV2qqARHVWNJd8ttBDKrAXM0Jq88R6Z3S/M+Zqu+KQgX9qah+s14/CM2JyHRZHnZpg8 X-Received: by 2002:a05:600c:108b:b0:3f5:878:c0c2 with SMTP id e11-20020a05600c108b00b003f50878c0c2mr1133893wmd.3.1693968094011; Tue, 05 Sep 2023 19:41:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1693968093; cv=none; d=google.com; s=arc-20160816; b=zB4ade1yCypvi3PvDvYFnr8x23/z5BQk0JnuPq9IA8wdnbIeVIpvN5s/y7WhVhmr51 MTrEsFLpPbovYLeDh8LKYxoWJbrBchJSyxar1o4gpNLCciQEpM+gJC/bhQXQu+9Bvzfl uRlU3mPIWKPi9PMzVg08uF84qC4tOfr+IdsqdTJ5ivwGBk9vypslYjIAPI/LKnZZ1mKR vnTGwhu83gn5ZcJSiWU+TYEaiguwTHz/2v9MCr5CoIrAou+A+g1TnwrV0BridBR//5FV XgmQNlecTXNVpEk7aP5BLOabfP4NBGi7sYob3Gl6MTGycevHRirWEenK88E3WhWSg59V Zbeg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=lPYCnBRLWg4g7sl74QYJVP75Z/zmBm7PNVaK8xYbfG8=; fh=Yz321xYbZlOZFLAVVWewQ+h9487s8fAdGcGeu++kLX8=; b=hyzfGLh7PE6aFk/6kn6OQnSy5bokWSylDF1Fvze25r9T/UfQaDyPLYgNr6pkitH5kE tMnz9HPZhvkEAM5k0Gb/2KCCizy1/phJ+FH6gTfOqxWf7W0sPkaX047gZ5sT4AkpbP3m q0tfm8zHUIGpTwa0d7YXRbkObr96Rbrn5yMjg+Zwr4jB71DhcpxdNFIvF2q7Lr/6YLwm cS2fj4v3lx+3cM4WC1oPKFgPiXW8KSFLWmWZHAaBfPMCRniXhHovfHv93R9aLS83plzD MxCpHcw5ltZwW6qNFYvGKSmglIheXmo188cDfv6/c7FeJNpc9BlvDUuFpq7rFKLrhQg8 /q2Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=mCGuD78X; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id f9-20020a056000128900b0030fcc2761basi6198473wrx.17.2023.09.05.19.41.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Sep 2023 19:41:33 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=mCGuD78X; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6F964866A0; Wed, 6 Sep 2023 04:41:10 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="mCGuD78X"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id A6882833DE; Wed, 6 Sep 2023 04:41:09 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pf1-x430.google.com (mail-pf1-x430.google.com [IPv6:2607:f8b0:4864:20::430]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 3899B866A0 for ; Wed, 6 Sep 2023 04:41:05 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pf1-x430.google.com with SMTP id d2e1a72fcca58-68a4dab8172so647493b3a.0 for ; Tue, 05 Sep 2023 19:41:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1693968063; x=1694572863; darn=lists.denx.de; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=lPYCnBRLWg4g7sl74QYJVP75Z/zmBm7PNVaK8xYbfG8=; b=mCGuD78XqGtgC4ymz8mMQMfZmYCeiD0oe7074mODiiOcin2PChvApLsJG+M/1j/uKo z0v0d6m9vr935Mv4ZEwhBciOsQePydtyhd0u5HxikicYYTqXsmVHhLbb+0pyBEAjwLe1 qsBJ2ft9hKoIbu+K4pT+f1AApIocE67ZBrzA3tkwZYi5E27u1jMbVHsGQYZD5JqUU56x 3dQaaftDzWm8vHMZJ1rNP2VXmr9Rlb08vsYvuF6AesSbg4yuiaw0KbF3ewC6vt9Dgkz8 dWPGIQGGr9HC+1d/JV6jikx7/6XGEKnxaNaSR8wMBjtepfDJV3QVuiGFVcFL9PMnsBRv JxCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1693968063; x=1694572863; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=lPYCnBRLWg4g7sl74QYJVP75Z/zmBm7PNVaK8xYbfG8=; b=HSmMIkIYT8VTgcGNF3I1XJWyEF/wNH9AcG25wCaGVKfxyVgvhIVBSmIkBHbSHELwwb LIHQ4X/UVkjd8WMpfKxCOshupqRdn57BsHoU8o3SYN0t2P9xygwq/EBW4FoOCYCaU3/Q Iplar0w3wLQdapyJNeLOVFann6daiSHaxcnnDE5s2U5aJrG8wdmQLLVF/mNcaVbFCvd8 0LzhG8d/h66By3AP/wOx/Y3caYQe8NgPLuomTFhCJd9Rd0IZzQCw5HquWdacRlodvpx0 sjf1E134PD4EnB/osITsYH/js48++lXBV5rM8lURxnH9xiCHAoZ0wZ673ohaFfLb0VoZ sgcA== X-Gm-Message-State: AOJu0YzqVpbMrjldUrRnNsAPw3kn3xe+1QgTPRIYZiD+nCQL3eqh5MJY coS3s8yZeyDu9rBKf7mQeGVKnWG64ej++QIt6MWqxw== X-Received: by 2002:a05:6a20:a122:b0:13e:1d49:7249 with SMTP id q34-20020a056a20a12200b0013e1d497249mr19515911pzk.2.1693968063455; Tue, 05 Sep 2023 19:41:03 -0700 (PDT) Received: from octopus.. ([2400:4050:c3e1:100:8294:a07d:b7e9:4033]) by smtp.gmail.com with ESMTPSA id c5-20020a6566c5000000b0056428865aadsm9145378pgw.82.2023.09.05.19.41.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Sep 2023 19:41:03 -0700 (PDT) From: AKASHI Takahiro To: u-boot@lists.denx.de Cc: etienne.carriere@st.com, michal.simek@amd.com, sjg@chromium.org, linus.walleij@linaro.org, Oleksii_Moisieiev@epam.com, AKASHI Takahiro Subject: [RFC 3/6] pinctrl: add scmi driver Date: Wed, 6 Sep 2023 11:40:08 +0900 Message-Id: <20230906024011.17488-4-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230906024011.17488-1-takahiro.akashi@linaro.org> References: <20230906024011.17488-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean This DM-compliant driver deals with SCMI pinctrl protocol and presents pinctrl devices exposed by SCMI firmware (server). Signed-off-by: AKASHI Takahiro --- drivers/pinctrl/Kconfig | 11 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-scmi.c | 537 +++++++++++++++++++++++++++++++++ 3 files changed, 549 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-scmi.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 75b3ff47a2e8..d02f5db550c8 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -256,6 +256,17 @@ config PINCTRL_SANDBOX Currently, this driver actually does nothing but print debug messages when pinctrl operations are invoked. +config PINCTRL_SCMI + bool "SCMI pinctrl driver" + depends on SCMI_FIRMWARE + select SCMI_PINCTRL + help + This enables pinctrl driver base on SCMI. + + The driver is controlled by a device tree node which contains + both the GPIO definitions and pin control functions for each + available multiplex function. + config PINCTRL_SINGLE bool "Single register pin-control and pin-multiplex driver" depends on DM diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index fc1f01a02cbd..a791df022b7d 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_PINCTRL_MSCC) += mscc/ obj-$(CONFIG_ARCH_MVEBU) += mvebu/ obj-$(CONFIG_ARCH_NEXELL) += nexell/ obj-$(CONFIG_PINCTRL_QE) += pinctrl-qe-io.o +obj-$(CONFIG_PINCTRL_SCMI) += pinctrl-scmi.o obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o obj-$(CONFIG_PINCTRL_STM32) += pinctrl_stm32.o diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c new file mode 100644 index 000000000000..3ebdad57b86c --- /dev/null +++ b/drivers/pinctrl/pinctrl-scmi.c @@ -0,0 +1,537 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 Linaro Limited + * Author: AKASHI Takahiro + */ + +#define LOG_CATEGORY UCLASS_PINCTRL + +#include +#include +#include +#include +#include +#include +#include + +/** + * struct scmi_pin - attributes for a pin + * @name: Name of pin + * @value: Value of pin + * @flags: A set of flags + * @function: Function selected + * @status: An array of status of configuration types + */ +struct scmi_pin { + char *name; + u32 value; + u32 flags; + unsigned int function; + u32 status[SCMI_PINCTRL_CONFIG_RESERVED]; +}; + +/** + * struct scmi_group - attributes for a group + * @name: Name of group + * @num_pins: A number of pins + * @pins: An array of pin id's + */ +struct scmi_group { + char *name; + unsigned int num_pins; + u16 *pins; +}; + +/** + * struct scmi_pinctrl_priv - private data for pinctrl device + * @num_pins: A number of pins + * @num_groups: A number of groups + * @num_functions: A number of functions + * @pins: An array of pins + * @groups: An array of groups + * @functions: An array of function names + */ +struct scmi_pinctrl_priv { + unsigned int num_pins; + unsigned int num_groups; + unsigned int num_functions; + struct scmi_pin *pins; + struct scmi_group *groups; + char **functions; +}; + +static const struct pinconf_param scmi_conf_params[] = { + { "default", SCMI_PINCTRL_CONFIG_DEFAULT, 1 }, + { "bias-bus-hold", SCMI_PINCTRL_CONFIG_BIAS_BUS_HOLD, 1 }, + { "bias-disable", SCMI_PINCTRL_CONFIG_BIAS_DISABLE, 1 }, + { "bias-high-impedance", SCMI_PINCTRL_CONFIG_BIAS_HI_IMPEDANCE, 1 }, + { "bias-pull-up", SCMI_PINCTRL_CONFIG_BIAS_PULL_UP, 1 }, + { "bias-pull-default", SCMI_PINCTRL_CONFIG_BIAS_PULL_DEF, 1 }, + { "bias-pull-down", SCMI_PINCTRL_CONFIG_BIAS_PULL_DOWN, 1 }, + { "drive-open-drain", SCMI_PINCTRL_CONFIG_DRIVE_OPEN_DRAIN, 1 }, + { "drive-open-source", SCMI_PINCTRL_CONFIG_DRIVE_OPEN_SOURCE, 1 }, + { "drive-push-pull", SCMI_PINCTRL_CONFIG_DRIVE_PUSH_PULL, 1 }, + { "drive-strength", SCMI_PINCTRL_CONFIG_DRIVE_STRENGTH, 0 }, + { "input-debounce", SCMI_PINCTRL_CONFIG_INPUT_DEBOUNCE, 0 }, + { "input-mode", SCMI_PINCTRL_CONFIG_INPUT_MODE, 1 }, + { "pull-mode", SCMI_PINCTRL_CONFIG_PULL_MODE, 0 }, + { "input-value", SCMI_PINCTRL_CONFIG_INPUT_VALUE, 0 }, + { "input-schmitt", SCMI_PINCTRL_CONFIG_INPUT_SCHMITT, 1 }, + { "low-power-mode", SCMI_PINCTRL_CONFIG_LOW_POWER_MODE, 1 }, + { "output-mode", SCMI_PINCTRL_CONFIG_OUTPUT_MODE, 1 }, + { "output-value", SCMI_PINCTRL_CONFIG_OUTPUT_VALUE, 0 }, + { "power-source", SCMI_PINCTRL_CONFIG_POWER_SOURCE, 0 }, + { "slew-rate", SCMI_PINCTRL_CONFIG_SLEW_RATE, 0 }, +}; + +/** + * pinctrl_get_name - get a name + * @dev: SCMI pinctrl device + * @type: Type of id + * @id: Identifier of pin, group or function + * + * Get a name of @id. + * @type can be SCMI_PINCTRL_TYPE_PIN, GROUP or FUNCTION. + * An extended name is returned if it is provided. + * + * Return: A pointer to the name, NULL if failed. + */ +static char *pinctrl_get_name(struct udevice *dev, unsigned int type, + unsigned int id) +{ + u8 *name, *extended_name; + bool extended; + int ret; + + ret = scmi_pinctrl_attrs(dev, id, type, &extended, &name); + if (ret) { + dev_err(dev, "failed to get attributes (%d)\n", ret); + return NULL; + } + + if (!extended) + return name; + + ret = scmi_pinctrl_name_get(dev, id, type, &extended_name); + if (ret) { + dev_err(dev, "failed to get extended_name (%d)\n", ret); + return name; + } + + free(name); + return extended_name; +} + +/** + * get_pins_count - Get the number of selectable pins + * @dev: SCMI pinctrl device to use + * + * Get the number of selectable named pins available in this driver + * + * Return: a number of pins + */ +static int scmi_get_pins_count(struct udevice *dev) +{ + struct scmi_pinctrl_priv *priv = dev_get_priv(dev); + + return priv->num_pins; +} + +/** + * get_pin_name - Get the name of a pin + * @dev: SCMI pinctrl device of the pin + * @selector: The pin selector + * + * Get the name of a pin + * + * Return: a pointer to the name of the pin + */ +static const char *scmi_get_pin_name(struct udevice *dev, unsigned int selector) +{ + return pinctrl_get_name(dev, SCMI_PINCTRL_TYPE_PIN, selector); +} + +/** + * get_pin_muxing - Show pin muxing + * @dev: SCMI pinctrl device to use + * @selector: Pin selector + * @buf: Buffer to fill with pin muxing description + * @size: Size of @buf + * + * Create a displayable information in @buf about the muxing of a given pin. + * + * @Return: 0 if OK, or negative error code on failure + */ +static int scmi_get_pin_muxing(struct udevice *dev, unsigned int selector, + char *buf, int size) +{ + struct scmi_pinctrl_priv *priv = dev_get_priv(dev); + char tmp[100]; + int i; + + if (priv->pins[selector].function == UINT_MAX) { + strlcpy(buf, "", size); + return 0; + } + + sprintf(tmp, "%s", priv->functions[priv->pins[selector].function]); + strlcpy(buf, tmp, size); + + for (i = 0; i < SCMI_PINCTRL_CONFIG_RESERVED; i++) { + /* TODO: distinguish 0 and "disabled" in status */ + if (priv->pins[selector].status[i]) { + strlcat(buf, " ", size); + strlcat(buf, scmi_conf_params[i].property, size); + } + } + strlcat(buf, ".", size); + + return 0; +} + +/** + * get_groups_count - Get the number of selectable groups + * @dev: SCMI pinctrl device to use + * + * Get a number of selectable groups + * + * Return: a number of selectable named groups available in the driver + */ +static int scmi_get_groups_count(struct udevice *dev) +{ + struct scmi_pinctrl_priv *priv = dev_get_priv(dev); + + return priv->num_groups; +} + +/** + * get_group_name - Get the name of a group + * @dev: SCMI pinctrl device of the group + * @selector: The group selector + * + * Ge the name of a group + * + * Return: a pointer to the name of the group + */ +static const char *scmi_get_group_name(struct udevice *dev, + unsigned int selector) +{ + return pinctrl_get_name(dev, SCMI_PINCTRL_TYPE_GROUP, selector); +} + +/** + * get_functions_count - Get the number of selectable functions + * @dev: SCMI pinctrl device to use + * + * Get a number of selectable functions + * + * Return: a number of selectable named functions available in this driver + */ +static int scmi_get_functions_count(struct udevice *dev) +{ + struct scmi_pinctrl_priv *priv = dev_get_priv(dev); + + return priv->num_functions; +} + +/** + * get_function_name - Get the name of a function + * @dev: SCMI pinmux device of the function + * @selector: The function selector + * + * Get a name of a function + * + * Return: a pointer to the function name of the muxing selector + */ +static const char *scmi_get_function_name(struct udevice *dev, + unsigned int selector) +{ + return pinctrl_get_name(dev, SCMI_PINCTRL_TYPE_FUNCTION, selector); +} + +/** + * pinmux_set - Mux a pin to a function + * @dev: SCMI pinctrl device to use + * @pin_selector: The pin selector + * @func_selector: The func selector + * + * Set a function, @function_selector, to @pin_selector. + * + * Return: 0 if OK, or negative error code on failure + */ +static int scmi_pinmux_set(struct udevice *dev, unsigned int pin_selector, + unsigned int func_selector) +{ + struct scmi_pinctrl_priv *priv = dev_get_priv(dev); + int ret; + + ret = scmi_pinctrl_function_select(dev, pin_selector, func_selector, + SCMI_PINCTRL_TYPE_PIN); + if (ret) { + dev_err(dev, "failed to select function (%d)\n", ret); + return ret; + } + + priv->pins[pin_selector].function = func_selector; + + return 0; +} + +/** + * pinmux_group_set - Mux a group of pins to a function + * @dev: SCMI pinctrl device to use + * @group_selector: The group selector + * @func_selector: The func selector + * + * Set a function, @function_selector, to @group_selector. + * + * @Return: 0 if OK, or negative error code on failure + */ +static int scmi_pinmux_group_set(struct udevice *dev, + unsigned int group_selector, + unsigned int func_selector) +{ + struct scmi_pinctrl_priv *priv = dev_get_priv(dev); + int i, ret; + + ret = scmi_pinctrl_function_select(dev, group_selector, func_selector, + SCMI_PINCTRL_TYPE_GROUP); + if (ret) { + dev_err(dev, "failed to select function (%d)\n", ret); + return ret; + } + + for (i = 0; i < priv->groups[group_selector].num_pins; i++) + priv->pins[priv->groups[group_selector].pins[i]].function = + func_selector; + + return 0; +} + +/* TODO: may be driver-specific */ +/** + * pinmux_property_set - Enable a pinmux group + * @dev: SCMI pinctrl device to use + * @pinmux_group: A u32 representing the pin identifier and mux + * settings. + * + * Mux a single pin to a single function based on a driver-specific + * pinmux group. + * The format of @pinmux_group follows ... + * + * Return: Pin selector for the muxed pin if OK, or negative error code on + * failure + */ +static int scmi_pinmux_property_set(struct udevice *dev, u32 pinmux_group) +{ + unsigned int pin_selector = pinmux_group & 0xFFFF; + unsigned int func_selector = pinmux_group >> 16; + int ret; + + ret = scmi_pinmux_set(dev, pin_selector, func_selector); + + return ret ? ret : pin_selector; +} + +/** + * pinconf_set - Configure an individual pin with a parameter + * @dev: SCMI pinctrl device to use + * @pin_selector: The pin selector + * @param: An &enum pin_config_param from @pinconf_params + * @argument: The argument to this param from the device tree, or + * @pinconf_params.default_value + * + * Configure @param of a pin, @pin_selector, with @argument. + * + * @Return: 0 if OK, or negative error code on failure + */ +static int scmi_pinconf_set(struct udevice *dev, unsigned int pin_selector, + unsigned int param, unsigned int argument) +{ + struct scmi_pinctrl_priv *priv = dev_get_priv(dev); + struct scmi_pin_entry config; + int ret; + + config.type = param; + config.value = argument; + ret = scmi_pinctrl_config_set(dev, pin_selector, SCMI_PINCTRL_TYPE_PIN, + 1, &config); + if (ret) { + dev_err(dev, "failed to set config (%d)\n", ret); + return ret; + } + + if (param < SCMI_PINCTRL_CONFIG_RESERVED) + priv->pins[pin_selector].status[param] = argument; + + return 0; +} + +/** + * pinconf_group_set - Configure all pins in a group with a parameter + * @dev: SCmi pinctrl device to use + * @group_selector: The group selector + * @param: A &enum pin_config_param from @pinconf_params + * @argument: The argument to this param from the device tree, or + * @pinconf_params.default_value + * + * Configure @param of all the pins in a group, @group_selector, with @argument. + * + * @Return: 0 if OK, or negative error code on failure + */ +static int scmi_pinconf_group_set(struct udevice *dev, + unsigned int group_selector, + unsigned int param, unsigned int argument) +{ + struct scmi_pinctrl_priv *priv = dev_get_priv(dev); + struct scmi_pin_entry config; + int i, ret; + + config.type = param; + config.value = argument; + ret = scmi_pinctrl_config_set(dev, group_selector, + SCMI_PINCTRL_TYPE_GROUP, 1, &config); + if (ret) { + dev_err(dev, "failed to set config (%d)\n", ret); + return ret; + } + + if (param >= SCMI_PINCTRL_CONFIG_RESERVED) + return 0; + + for (i = 0; i < priv->groups[group_selector].num_pins; i++) + priv->pins[priv->groups[group_selector].pins[i]].status[param] = + argument; + + return 0; +} + +const struct pinctrl_ops scmi_pinctrl_ops = { + .get_pins_count = scmi_get_pins_count, + .get_pin_name = scmi_get_pin_name, + .get_pin_muxing = scmi_get_pin_muxing, + .get_groups_count = scmi_get_groups_count, + .get_group_name = scmi_get_group_name, + .get_functions_count = scmi_get_functions_count, + .get_function_name = scmi_get_function_name, + .pinmux_set = scmi_pinmux_set, + .pinmux_group_set = scmi_pinmux_group_set, + .pinmux_property_set = scmi_pinmux_property_set, + .pinconf_num_params = ARRAY_SIZE(scmi_conf_params), + .pinconf_params = scmi_conf_params, + .pinconf_set = scmi_pinconf_set, + .pinconf_group_set = scmi_pinconf_group_set, + .set_state = pinctrl_generic_set_state, +}; + +/** + * scmi_pinctrl_probe - probe a device + * @dev: SCMI pinctrl device + * + * Probe and initialize a pinctrl device. + * + * Return: 0 on success, error code on failure + */ +static int scmi_pinctrl_probe(struct udevice *dev) +{ + struct scmi_pinctrl_priv *priv = dev_get_priv(dev); + u32 version; + char *name; + int i, ret; + + ret = devm_scmi_of_get_channel(dev); + if (ret) { + dev_err(dev, "failed to get channel (%d)\n", ret); + return ret; + } + + ret = scmi_generic_protocol_version(dev, SCMI_PROTOCOL_ID_PIN_CONTROL, + &version); + if (ret || version < SCMI_PIN_CONTROL_PROTOCOL_VERSION) { + dev_err(dev, "protocol version doesn't match (%d)\n", version); + return -EINVAL; + } + + ret = scmi_pinctrl_protocol_attrs(dev, &priv->num_pins, + &priv->num_groups, + &priv->num_functions); + if (ret) { + dev_err(dev, "failed to get protocol attributes (%d)\n", ret); + return ret; + } + + priv->pins = calloc(sizeof(struct scmi_pin), priv->num_pins); + if (!priv->pins) { + dev_err(dev, "memory not available\n"); + return -ENOMEM; + } + for (i = 0; i < priv->num_pins; i++) { + priv->pins[i].function = UINT_MAX; /* unknown yet */ + name = scmi_get_pin_name(dev, i); + if (!name) { + dev_err(dev, "failed to get pin name\n"); + return ret; + } + priv->pins[i].name = strdup(name); + free(name); + if (!priv->pins[i].name) { + dev_err(dev, "memory not available\n"); + return -ENOMEM; + } + } + + priv->groups = calloc(sizeof(struct scmi_group), priv->num_groups); + if (!priv->groups) + return -ENOMEM; + for (i = 0; i < priv->num_groups; i++) { + name = scmi_get_group_name(dev, i); + if (!name) { + dev_err(dev, "failed to get group name\n"); + return ret; + } + priv->groups[i].name = strdup(name); + free(name); + if (!priv->groups[i].name) { + dev_err(dev, "memory not available\n"); + return -ENOMEM; + } + + ret = scmi_pinctrl_list_assocs(dev, i, SCMI_PINCTRL_TYPE_GROUP, + &priv->groups[i].pins); + if (ret < 0) { + dev_err(dev, "failed to enumerate pins (%d)\n", ret); + return ret; + } + + priv->groups[i].num_pins = ret; + } + + priv->functions = calloc(sizeof(char *), priv->num_functions); + if (!priv->functions) { + dev_err(dev, "memory not available\n"); + return -ENOMEM; + } + for (i = 0; i < priv->num_functions; i++) { + name = scmi_get_function_name(dev, i); + if (!name) { + dev_err(dev, "failed to get group name\n"); + return ret; + } + priv->functions[i] = strdup(name); + free(name); + if (!priv->functions[i]) { + dev_err(dev, "memory not available\n"); + return -ENOMEM; + } + } + + return 0; +} + +U_BOOT_DRIVER(scmi_pinctrl) = { + .name = "scmi_pinctrl", + .id = UCLASS_PINCTRL, + .ops = &scmi_pinctrl_ops, + .probe = scmi_pinctrl_probe, + .priv_auto = sizeof(struct scmi_pinctrl_priv), +}; From patchwork Wed Sep 6 02:40:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 720399 Delivered-To: patch@linaro.org Received: by 2002:adf:d08b:0:b0:31d:da82:a3b4 with SMTP id y11csp2461672wrh; Tue, 5 Sep 2023 19:41:45 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFhdEXGPyAlQkP5eLmkOlUxNJec6bpslSrFSLbZWaVxMsnBRH9FNz8NAIMwPsiMl+sc8j17 X-Received: by 2002:adf:ce8b:0:b0:31c:6525:770d with SMTP id r11-20020adfce8b000000b0031c6525770dmr1187087wrn.1.1693968105208; Tue, 05 Sep 2023 19:41:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1693968105; cv=none; d=google.com; s=arc-20160816; b=GVqVKa4NFJ/jg6XKou6RsF79WeHbq6wdnL/J3Ob2fRdpSy5vJI8/e7noTQ8ABB71VO zyvtCvy+HoH5f8wZn3jJNiXFdMjMPMWcb4lyJxJHlXtkQ62Z4LQnvfZ9ngwQPdD+lqPc ArzX3hmvYRhR1S32O7YvagLOIZoN+LC/kYVkne2VBmoDKR/SNcqReS88KsjjNAYrh/Fg IWYW0DfBMPmtNNxh6btmsmYYsGQVgkzJhCuOL2U1HFaa/y5M0u74LKhtCDCA2zqtlREA sncCBKS2sYN+qkEdOZHkNjgkKbVojnoPGs05xk5Wgdg39tQc3xK6GtC7b9u3tK5LfuCF liIw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=gJ/cP6pxLpHcUCBMifor8Z4cNVKkDimfyI0l3gabecs=; fh=Yz321xYbZlOZFLAVVWewQ+h9487s8fAdGcGeu++kLX8=; b=Fc32/lVuhv+2oVFDRBN704TQxdHja2ALTkJBipk4+qUX1uhfP5IVdzDeHvMWx02DRQ yyKFDM+rIaPKC96oY3g21sxaQGIUNRRYv3/IXAKHG7p/bmDD3X+WNgyUyUfh1PFyQ5FI c/OAVqj5NYyHdRelSRaarhViqMyS+P+9bHUOmZjMMPCWRXGsoMl9BzMv5B295OclTIsW 4eDOIig6qy88JM6UeCtYOr1De5uQ4Adlj4EGcADX4S2zYF64Pow2Zh+I6tGlUoHqEeIi BEBl5DPGrROofgIVg50Dfviyr40jnyQNMRNsIT7LJ0rtFKXakZZ7bbny2nufQPx+XDgf R2Dw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=rgmvNNiL; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id r15-20020adfe68f000000b003179e275374si6499320wrm.114.2023.09.05.19.41.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Sep 2023 19:41:45 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=rgmvNNiL; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id B5D68865A6; Wed, 6 Sep 2023 04:41:12 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="rgmvNNiL"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id B2ABC8679F; Wed, 6 Sep 2023 04:41:11 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-ot1-x330.google.com (mail-ot1-x330.google.com [IPv6:2607:f8b0:4864:20::330]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 4310A86590 for ; Wed, 6 Sep 2023 04:41:07 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-ot1-x330.google.com with SMTP id 46e09a7af769-6bf106fb6a0so656944a34.0 for ; Tue, 05 Sep 2023 19:41:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1693968066; x=1694572866; darn=lists.denx.de; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=gJ/cP6pxLpHcUCBMifor8Z4cNVKkDimfyI0l3gabecs=; b=rgmvNNiL9ysSMPaGrvBWZJN9b18IOwE79BSZxLPK1Y4sYPCkTndVNo94yvmFl8g53q kP/weAbLVkK28fhhC4FvUP/Q2kXUKse9TXP41m70dg27FnQaHGDePCINgUU0wXvsVowO ACp3ZmlVawDIOyzyYCz7dkTbogtLrCol7JMY0SRCDd814IWxhWxqie6VDggbfJ1Kdu/R NQCvizKt+QQswFCqigOONz4Ce624NsuZBdbk5CZF1cgnUXs30g0bJfu7Ui/aUik28pXs QUYHIKpMJvWMKoR/XkntMnHKImDOp03SeHLu56oTSJs8c7MnKwjL8FFo8OKmx/PLtn4l Ki7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1693968066; x=1694572866; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=gJ/cP6pxLpHcUCBMifor8Z4cNVKkDimfyI0l3gabecs=; b=Cad3wnkilC3vcmHUfhI26QMVd/EpvkBA2V5NnaEz5ryCsZF7MKnkt4e9JUS9OypZSS Ks+PpRqPCmyod7xc/h/xL3ipB9m4e0GFdpzbs9pg966Pai6UbEnFc4eQwQ+smR5yXAcB F+pZvPfUaColx9vsrXCnSDcQxaedYFiNCK9YTaGVu/sPHwo6/XJpDG1jqr+Dyi7hhWUf miSgYW3hy5ZMc5kfQ0yl88T9c2DO4SuYmYX9RHo8MBpK9SFfdp96a6yewe8yTyhDTcgh yQ5zeJ4DiCUeqTErSi1xC+fbqnQBrr/mVjhYqfNxJbKcoq0DjK7PbpDTUZTB277fm5qL euQg== X-Gm-Message-State: AOJu0YxBtIb31dA2qa2YF/YudchKy67RM9jKnsHIXU3Rp40nISd1wi3k ZWwYngjxpHY/lXrBJ++E7FJhaOQQP37RyeEsw62QBg== X-Received: by 2002:a05:6830:46a3:b0:6bd:9d65:fce with SMTP id ay35-20020a05683046a300b006bd9d650fcemr14260807otb.2.1693968065689; Tue, 05 Sep 2023 19:41:05 -0700 (PDT) Received: from octopus.. ([2400:4050:c3e1:100:8294:a07d:b7e9:4033]) by smtp.gmail.com with ESMTPSA id c5-20020a6566c5000000b0056428865aadsm9145378pgw.82.2023.09.05.19.41.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Sep 2023 19:41:05 -0700 (PDT) From: AKASHI Takahiro To: u-boot@lists.denx.de Cc: etienne.carriere@st.com, michal.simek@amd.com, sjg@chromium.org, linus.walleij@linaro.org, Oleksii_Moisieiev@epam.com, AKASHI Takahiro Subject: [RFC 4/6] gpio: add scmi driver based on pinctrl Date: Wed, 6 Sep 2023 11:40:09 +0900 Message-Id: <20230906024011.17488-5-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230906024011.17488-1-takahiro.akashi@linaro.org> References: <20230906024011.17488-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean This DM-compliant driver deals with SCMI pinctrl protocol and presents gpio devices exposed by SCMI firmware (server). Signed-off-by: AKASHI Takahiro --- drivers/pinctrl/pinctrl-scmi.c | 544 ++++++++++++++++++++++++++++++++- 1 file changed, 539 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/pinctrl-scmi.c b/drivers/pinctrl/pinctrl-scmi.c index 3ebdad57b86c..73d385bdbfcc 100644 --- a/drivers/pinctrl/pinctrl-scmi.c +++ b/drivers/pinctrl/pinctrl-scmi.c @@ -11,21 +11,20 @@ #include #include #include +#include #include +#include +#include #include /** * struct scmi_pin - attributes for a pin * @name: Name of pin - * @value: Value of pin - * @flags: A set of flags * @function: Function selected * @status: An array of status of configuration types */ struct scmi_pin { char *name; - u32 value; - u32 flags; unsigned int function; u32 status[SCMI_PINCTRL_CONFIG_RESERVED]; }; @@ -308,7 +307,6 @@ static int scmi_pinmux_group_set(struct udevice *dev, return 0; } -/* TODO: may be driver-specific */ /** * pinmux_property_set - Enable a pinmux group * @dev: SCMI pinctrl device to use @@ -424,6 +422,539 @@ const struct pinctrl_ops scmi_pinctrl_ops = { .set_state = pinctrl_generic_set_state, }; +#if CONFIG_IS_ENABLED(DM_GPIO) +/* + * GPIO part + */ + +/** + * struct scmi_pinctrl_gpio_plat - platform data + * @pinctrl_dev: Associated SCMI pinctrl device + * @gpio_map: A list of gpio mapping information + * @name: Name of ? + * @ngpios: A number of gpio pins + */ +struct scmi_pinctrl_gpio_plat { + struct list_head gpio_map; + char *name; + u32 ngpios; +}; + +/** + * struct scmi_pinctrl_gpio_map - gpio mapping information + * @gpio_pin: Start gpio pin selector + * @pinctrl_pin: Mapped start pinctrl pin selector, used for linear mapping + * @pinctrl_group: Name of an associated group, used for group namee mapping + * @num_pins: A number of pins + * @node: Node for a mapping list + */ +struct scmi_pinctrl_gpio_map { + struct udevice *pinctrl_dev; + u32 gpio_pin; + u32 pinctrl_pin; + u16 *pinctrl_group; + u32 num_pins; + struct list_head node; +}; + +/** + * map_to_id - Map a gpio pin offset to a pinctrl pin selector + * @dev: SCMI pinctrl device + * @offset: Pin offset + * @id: Pinctrl pin selector + * + * Map a gpio pin offset, @offset, to an associated pinctrl pin selector + * + * Return: 0 on success, -1 on failure + */ +static int map_to_id(struct udevice *dev, unsigned int offset, + struct udevice **pinctrl_dev, u32 *id) +{ + struct scmi_pinctrl_gpio_plat *plat = dev_get_plat(dev); + struct scmi_pinctrl_gpio_map *map; + + /* if no mapping is defined, return 1:1 pin */ + if (list_empty(&plat->gpio_map)) { + uclass_first_device(UCLASS_PINCTRL, pinctrl_dev); + if (!*pinctrl_dev) + return -1; + + *id = offset; + return 0; + } + + list_for_each_entry(map, &plat->gpio_map, node) { + if (offset >= map->gpio_pin && + offset < (map->gpio_pin + map->num_pins)) { + *pinctrl_dev = map->pinctrl_dev; + if (!pinctrl_dev) + return -1; + + if (map->pinctrl_group) + *id = map->pinctrl_group[offset + - map->gpio_pin]; + else + *id = map->pinctrl_pin + + (offset - map->gpio_pin); + + return 0; + } + } + + return -1; +} + +/** + * scmi_gpio_get_value - Get a value of a gpio pin + * @dev: SCMI gpio device + * @offset: Pin offset + * + * Get a value of a gpio pin in @offset + * + * Return: Value of a pin on success, error code on failure + */ +static int scmi_gpio_get_value(struct udevice *dev, unsigned int offset) +{ + struct scmi_pinctrl_priv *priv; + u32 id; + struct udevice *pinctrl_dev; + struct scmi_pin_entry *config; + int config_type, ret; + + if (map_to_id(dev, offset, &pinctrl_dev, &id)) { + dev_err(dev, "Invalid pin: %u\n", offset); + return -EINVAL; + } + + priv = dev_get_priv(pinctrl_dev); + if (priv->pins[id].status[SCMI_PINCTRL_CONFIG_INPUT_MODE]) { + config_type = SCMI_PINCTRL_CONFIG_INPUT_VALUE; + } else if (priv->pins[id].status[SCMI_PINCTRL_CONFIG_OUTPUT_MODE]) { + config_type = SCMI_PINCTRL_CONFIG_OUTPUT_VALUE; + } else { + dev_err(dev, "Invalid pin mode: %u\n", offset); + return -EINVAL; + } + + ret = scmi_pinctrl_config_get(pinctrl_dev, id, false, + SCMI_PINCTRL_TYPE_PIN, config_type, + &config); + if (ret) { + dev_err(dev, "config_get failed (%d)\n", ret); + return ret; + } + + return config->value; +} + +/** + * config_pin_set - Configure a pinctrl pin + * @dev: SCMI pinctrl device + * @id: Pin selector + * @config_type: Configuration type + * @value: Value + * + * Set a configuration of @config_type of a pinctrl pin, @id, to @value. + * + * Return: 0 on success, error code on failure + */ +static int config_pin_set(struct udevice *dev, u32 id, u32 config_type, + u32 value) +{ + struct scmi_pinctrl_priv *priv = dev_get_priv(dev); + struct scmi_pin_entry config; + int ret; + + config.type = config_type; + config.value = value; + ret = scmi_pinctrl_config_set(dev, id, SCMI_PINCTRL_TYPE_PIN, + 1, &config); + if (ret) { + dev_err(dev, "config_set failed (%d)\n", ret); + return ret; + } + + priv->pins[id].status[config_type] = value; + + return 0; +} + +/** + * scmi_gpio_set_value - Set a value of a gpio pin + * @dev: SCMI gpio device + * @offset: Pin offset + * @value: Value + * + * Set a value of a gpio pin in @offset to @value. + * + * Return: 0 on success, error code on failure + */ +static int scmi_gpio_set_value(struct udevice *dev, unsigned int offset, + int value) +{ + struct udevice *pinctrl_dev; + u32 id; + + if (map_to_id(dev, offset, &pinctrl_dev, &id)) { + dev_err(dev, "Invalid pin: %u\n", offset); + return -EINVAL; + } + + return config_pin_set(pinctrl_dev, id, + SCMI_PINCTRL_CONFIG_OUTPUT_VALUE, + (u32)value); +} + +/** + * scmi_gpio_get_function - Get a gpio function of a gpio pin + * @dev: SCMI gpio device + * @offset: Pin offset + * + * Get a gpio function of a gpio pin in @offset. + * + * Return: GPIOF_OUTPUT or GPIO_INPUT on success, otherwise GPIOF_UNKNOWN + */ +static int scmi_gpio_get_function(struct udevice *dev, unsigned int offset) +{ + struct udevice *pinctrl_dev; + u32 id; + struct scmi_pin_entry *config; + int ret; + + if (map_to_id(dev, offset, &pinctrl_dev, &id)) { + dev_err(dev, "Invalid pin: %u\n", offset); + return -EINVAL; + } + + ret = scmi_pinctrl_config_get(pinctrl_dev, id, false, + SCMI_PINCTRL_TYPE_PIN, + SCMI_PINCTRL_CONFIG_INPUT_MODE, &config); + if (!ret && config->value == 1) + return GPIOF_INPUT; + + ret = scmi_pinctrl_config_get(pinctrl_dev, id, false, + SCMI_PINCTRL_TYPE_PIN, + SCMI_PINCTRL_CONFIG_OUTPUT_MODE, + &config); + if (!ret && config->value == 1) + return GPIOF_OUTPUT; + + return GPIOF_UNKNOWN; +} + +/** + * set_flags - Adjust GPIO flags + * @dev: SCMI gpio device + * @offset: Pin offset + * @flags: New flags value + * + * This function should set up the GPIO configuration according to information + * provided by @flags (GPIOD_xxx). + * + * @return 0 if OK, otherwise -ve on error + */ +static int scmi_gpio_set_flags(struct udevice *dev, unsigned int offset, + ulong flags) +{ + struct udevice *pinctrl_dev; + struct scmi_pin_entry config[5]; /* 5 is enough for now */ + u32 id; + struct scmi_pinctrl_priv *priv; + int i = 0, ret; + + if (map_to_id(dev, offset, &pinctrl_dev, &id)) { + dev_err(dev, "Invalid pin: %u\n", offset); + return -EINVAL; + } + + if (flags & GPIOD_IS_OUT) { + config[i].type = SCMI_PINCTRL_CONFIG_INPUT_MODE; + config[i++].value = 0; + + config[i].type = SCMI_PINCTRL_CONFIG_OUTPUT_MODE; + config[i++].value = 1; + config[i].type = SCMI_PINCTRL_CONFIG_OUTPUT_VALUE; + config[i++].value = (u32)!!(flags & GPIOD_IS_OUT_ACTIVE); + } else if (flags & GPIOD_IS_IN) { + config[i].type = SCMI_PINCTRL_CONFIG_OUTPUT_MODE; + config[i++].value = 0; + + config[i].type = SCMI_PINCTRL_CONFIG_INPUT_MODE; + config[i++].value = 1; + } + + if (flags & GPIOD_OPEN_DRAIN) { + config[i].type = SCMI_PINCTRL_CONFIG_DRIVE_OPEN_DRAIN; + config[i++].value = 1; + } else if (flags & GPIOD_OPEN_SOURCE) { + config[i].type = SCMI_PINCTRL_CONFIG_DRIVE_OPEN_SOURCE; + config[i++].value = 1; + } + + if (flags & GPIOD_PULL_UP) { + config[i].type = SCMI_PINCTRL_CONFIG_BIAS_PULL_UP; + config[i++].value = 1; + } else if (flags & GPIOD_PULL_DOWN) { + config[i].type = SCMI_PINCTRL_CONFIG_BIAS_PULL_DOWN; + config[i++].value = 1; + } + + ret = scmi_pinctrl_config_set(pinctrl_dev, id, SCMI_PINCTRL_TYPE_PIN, + i, config); + if (ret) { + dev_err(dev, "config_set failed (%d)\n", ret); + return ret; + } + + /* update local status */ + priv = dev_get_priv(pinctrl_dev); + + if (flags & GPIOD_IS_OUT) { + priv->pins[id].status[SCMI_PINCTRL_CONFIG_OUTPUT_MODE] = 1; + priv->pins[id].status[SCMI_PINCTRL_CONFIG_OUTPUT_VALUE] = 1; + + priv->pins[id].status[SCMI_PINCTRL_CONFIG_INPUT_MODE] = 0; + } else if (flags & GPIOD_IS_IN) { + priv->pins[id].status[SCMI_PINCTRL_CONFIG_INPUT_MODE] = 1; + priv->pins[id].status[SCMI_PINCTRL_CONFIG_OUTPUT_MODE] = 0; + } + + if (flags & GPIOD_OPEN_DRAIN) + priv->pins[id].status[SCMI_PINCTRL_CONFIG_DRIVE_OPEN_DRAIN] = 1; + else if (flags & GPIOD_OPEN_SOURCE) + priv->pins[id].status[SCMI_PINCTRL_CONFIG_DRIVE_OPEN_SOURCE] = + 1; + + if (flags & GPIOD_PULL_UP) + priv->pins[id].status[SCMI_PINCTRL_CONFIG_BIAS_PULL_UP] = 1; + else if (flags & GPIOD_PULL_DOWN) + priv->pins[id].status[SCMI_PINCTRL_CONFIG_BIAS_PULL_DOWN] = 1; + + return 0; +} + +/** + * lookup_pin_group - find out a list of pins for group name + * @dev: SCMI pinctrl device + * @name: Name of a group + * @num_pins: Pointer to a number of pins + * @pins: Pointer to array of pin selectors + * + * Look up a group named @name and return a list of pin selectors associated with + * the group in @pins. + * + * Return: 0 on success, -1 on failure + */ +static int lookup_pin_group(struct udevice *dev, const char *name, + u32 *num_pins, u16 **pins) +{ + struct scmi_pinctrl_priv *priv = dev_get_priv(dev); + int i; + + for (i = 0; i < priv->num_groups; i++) + if (!strcmp(name, priv->groups[i].name)) { + *num_pins = priv->groups[i].num_pins; + *pins = priv->groups[i].pins; + return 0; + } + + return -1; +} + +/** + * get_pinctrl_dev - Get a pin control device at node + * @node: Reference to the node + * + * Get a pin control device at @node. + * + * Return: 0 on success, otherwise NULL + */ +static struct udevice *get_pinctrl_dev(ofnode *node) +{ + struct udevice *dev; + struct uclass *uc; + + if (uclass_get(UCLASS_PINCTRL, &uc)) + return NULL; + + uclass_foreach_dev(dev, uc) + if (dev->node_.np == node->np) + return dev; + + return NULL; +} + +/** + * scmi_gpio_probe - Probe a SCMI gpio device + * @dev: SCMI gpio device + * + * Probe and initialize a SCMI gpio device. + * + * 0 on success, error code on failure + */ +static int scmi_gpio_probe(struct udevice *dev) +{ + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct scmi_pinctrl_gpio_plat *plat = dev_get_plat(dev); + + struct scmi_pinctrl_gpio_map *range; + struct ofnode_phandle_args args; + const char *name; + int num_pins = 0, index, ret; + + uc_priv->bank_name = dev_read_string(dev, "gpio-bank-name"); + if (!uc_priv->bank_name) + uc_priv->bank_name = dev->name; + + INIT_LIST_HEAD(&plat->gpio_map); + for (index = 0; ; index++) { + ret = dev_read_phandle_with_args(dev, "gpio-ranges", + NULL, 3, index, &args); + if (ret) + break; + + range = malloc(sizeof(*range)); + if (!range) { + dev_err(dev, "Memory not available\n"); + return -ENOMEM; + } + + range->pinctrl_dev = get_pinctrl_dev(&args.node); + if (!range->pinctrl_dev) { + dev_err(dev, "Pin control device not found\n"); + return -ENODEV; + } + + /* make sure pinctrl is activated */ + ret = device_probe(range->pinctrl_dev); + if (ret) + return ret; + + if (args.args[2]) { + range->gpio_pin = args.args[0]; + range->pinctrl_pin = args.args[1]; + range->num_pins = args.args[2]; + range->pinctrl_group = NULL; + } else { + ret = of_property_read_string_index(dev_np(dev), + "gpio-ranges-group-names", + index, &name); + if (ret) { + dev_err(dev, + "gpio-ranges-group-names required\n"); + return ret; + } + + ret = lookup_pin_group(range->pinctrl_dev, name, + &range->num_pins, + &range->pinctrl_group); + if (ret) { + dev_err(dev, "Group not found: %s\n", name); + return -EINVAL; + } + + range->gpio_pin = args.args[0]; + } + num_pins += range->num_pins; + list_add_tail(&range->node, &plat->gpio_map); + } + + uc_priv->gpio_count = num_pins; + + return 0; +} + +static const struct dm_gpio_ops scmi_gpio_ops = { + .get_function = scmi_gpio_get_function, + .get_value = scmi_gpio_get_value, + .set_value = scmi_gpio_set_value, + .set_flags = scmi_gpio_set_flags, +}; + +static const struct udevice_id scmi_gpio_ids[] = { + { .compatible = "arm,scmi-gpio-generic" }, + { } +}; + +U_BOOT_DRIVER(scmi_gpio) = { + .name = "scmi_gpio", + .id = UCLASS_GPIO, + .of_match = scmi_gpio_ids, + .of_to_plat = scmi_gpio_probe, + .ops = &scmi_gpio_ops, + .plat_auto = sizeof(struct scmi_pinctrl_gpio_plat), +}; + +/** + * scmi_gpiochip_register - Create a pinctrl-controlled gpio device + * @parent: SCMI pinctrl device + * + * Create a pinctrl-controlled gpio device + * + * Return: 0 on success, error code on failure + */ +static int scmi_gpiochip_register(struct udevice *parent) +{ + ofnode node; + struct driver *drv; + struct udevice *gpio_dev; + int ret; + + /* TODO: recovery if failed */ + dev_for_each_subnode(node, parent) { + if (!ofnode_is_enabled(node)) + continue; + + if (!ofnode_read_prop(node, "gpio-controller", NULL)) + /* not a GPIO node */ + continue; + + drv = DM_DRIVER_GET(scmi_gpio); + if (!drv) { + dev_err(parent, "No gpio driver?\n"); + return -ENODEV; + } + + ret = device_bind(parent, drv, ofnode_get_name(node), NULL, + node, &gpio_dev); + if (ret) { + dev_err(parent, "failed to bind %s to gpio (%d)\n", + ofnode_get_name(node), ret); + return -ENODEV; + } + + return 0; + } + + return -ENODEV; +} + +/** + * scmi_pinctrl_bind - Bind a pinctrl-controlled gpio device + * @dev: SCMI pinctrl device + * + * Bind a pinctrl-controlled gpio device + * + * Return: 0 on success, error code on failure + */ +static int scmi_pinctrl_bind(struct udevice *dev) +{ + int ret; + + /* gpiochip register */ + if (CONFIG_IS_ENABLED(DM_GPIO)) { + ret = scmi_gpiochip_register(dev); + if (ret && ret != -ENODEV) { + dev_err(dev, "failed to register gpio driver (%d)\n", + ret); + return ret; + } + } + + return 0; +} +#endif /* CONFIG_DM_GPIO */ + /** * scmi_pinctrl_probe - probe a device * @dev: SCMI pinctrl device @@ -532,6 +1063,9 @@ U_BOOT_DRIVER(scmi_pinctrl) = { .name = "scmi_pinctrl", .id = UCLASS_PINCTRL, .ops = &scmi_pinctrl_ops, +#if CONFIG_IS_ENABLED(DM_GPIO) + .bind = scmi_pinctrl_bind, +#endif .probe = scmi_pinctrl_probe, .priv_auto = sizeof(struct scmi_pinctrl_priv), }; From patchwork Wed Sep 6 02:40:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 720400 Delivered-To: patch@linaro.org Received: by 2002:adf:d08b:0:b0:31d:da82:a3b4 with SMTP id y11csp2461716wrh; Tue, 5 Sep 2023 19:41:56 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEZsSJXDjA18LSlLuiPx0YthziW0olZTytwGjW+6T3NkYOeAFJxhhTlxNVrCqbuDjhpDHDE X-Received: by 2002:a5d:4f0e:0:b0:317:5d1c:9719 with SMTP id c14-20020a5d4f0e000000b003175d1c9719mr1159418wru.9.1693968116533; Tue, 05 Sep 2023 19:41:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1693968116; cv=none; d=google.com; s=arc-20160816; b=yDqpIfcGQLLeLbsZoj3W6LVaU1GMGIYOa+fh4TwicoOkFJWGZxN4SeDZ3+y8t3x77V TATzGEueWkcBSXWbczzuuXWKPWm76KGiSQvNX0+OTZq1nQj4l3erwvD/ONNfl0lZnOTY n00gmcn6DcSlGLJ6r4RCsDB6nvgDac8uf/OWPM1a92S6UoinQ3dPKl5YLlne0uWo5bv4 iFNFulq84H29omBcfRVpVV+mf7YyNtAz91jYOcKyyI11NibMNj/dGe5NP3bI9wGBUDuR KVoJvXN6eraapSROf5pJTMa05Oau/HcYNLzwLhwKrTfuIXgpLriTVpPXqNfs2gfjXduJ Cs1A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=bDaK2f2RDHI4ZFwb1T775mvqYxCcpP0UOfvoR0syY7s=; fh=Yz321xYbZlOZFLAVVWewQ+h9487s8fAdGcGeu++kLX8=; b=VlitPWLdLnRf/7qCnutC8i45CTdl51JepQpbO9iD3v759IvMlpKge/txj+wcm7QgRj v5IY/uaVv8uubneGa1QVe8Jyp9O+kJlaTezJqHI1jYbMjHC9cBOSckV6Z75svCxWuB1w N1M+Ty6qalHzwtT3PsLLc8fk8KEuOEM0fP27RDbNst34YclEn3j0NnOHPhiwM/Lm3FJF ycghlzj2MiC8d9wo8kWrUiQbtPY+OQIX4PbzxWyoCGP5n13F3aw2JwOytgSBDc8t/oKV dd52/BNkSUe/S8nY4qeiPsKwrDdI+KMEal7nRs3OvKhhbPCRTouDxWXMAoEik6pt1Duw L5ow== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="uMk5da/D"; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id h9-20020a5d4fc9000000b0031975c6a38bsi6114430wrw.635.2023.09.05.19.41.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Sep 2023 19:41:56 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="uMk5da/D"; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 05958865A8; Wed, 6 Sep 2023 04:41:16 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="uMk5da/D"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id B68C586963; Wed, 6 Sep 2023 04:41:14 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pj1-x1034.google.com (mail-pj1-x1034.google.com [IPv6:2607:f8b0:4864:20::1034]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id C8515865A8 for ; Wed, 6 Sep 2023 04:41:09 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pj1-x1034.google.com with SMTP id 98e67ed59e1d1-2684e225a6cso495161a91.1 for ; Tue, 05 Sep 2023 19:41:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1693968068; x=1694572868; darn=lists.denx.de; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=bDaK2f2RDHI4ZFwb1T775mvqYxCcpP0UOfvoR0syY7s=; b=uMk5da/DqHLLw4YpmsQ/3nn+B5FPGaUzhtLzxlaJxYRRAB96WEMQtWsDxdM9RDZpxA vJMkRh9PA3ScB5G66t5UieocWJNZ5vlcyLtfaBF68qAjHjIOk5bluEbPSoJ8GHy0R+/w 12YPvd3FL4XlORMwMTRWWBNfuhZbD8uh06E8wADylx5s9cRsh9qYmW6LyjMvywCVctkl M+u4O7esGawT+DvMhGoDUXUWbwIDn0zPo5+IXw4100jZsGYQyFDyNP79QJYcqY1SdEEt iZBTJDniUUr3RWFSZWmyzZ30WcNocDrQQ7PNx7QqAF2m3xM/BIyirLB5Cmv8Xs5aqcyX 95Gw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1693968068; x=1694572868; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=bDaK2f2RDHI4ZFwb1T775mvqYxCcpP0UOfvoR0syY7s=; b=Cv/TTXO9l4l8kcpFZD9Gt79q5sJq7dCqKUL51FTR+pP4zrby5QdKORG6r7J3zCBD/Y 9Xnfs9f7XZoU08Lvj1fjUjQ+DMfcw6nSH2CNHOOXccdudmLOuxeaeIRFIc3JT1r2YCzl KiH8L0a2W8kCVzHKO2zEjHYQAmkOAJKsvjllhoWry67t6NfHYyhg+ZIX7byX4P3buaMi A8l9TugMn5CvCplY0qoVlwyhN2EmaEB3Gf+MbEmpkLgC+jqjYQyM5riw0eBPNLMAbINq 66C02nm7O8NpzSGkwy1+/g1CWNDMFB4Kzraq2Ed9Ry+TwdRk5nshNyyRngVLYoh2vrGT 7xfA== X-Gm-Message-State: AOJu0YwjsTy9k35AVXZImAt3IMO4xf8FV6ohPG9soQHmqwn5YcFInJ4U COBp9MJJHc1etsnpCDLtIGQjqqx5qCneKPtBg9RiPA== X-Received: by 2002:a05:6a20:4289:b0:133:7a67:b477 with SMTP id o9-20020a056a20428900b001337a67b477mr20211617pzj.1.1693968067782; Tue, 05 Sep 2023 19:41:07 -0700 (PDT) Received: from octopus.. ([2400:4050:c3e1:100:8294:a07d:b7e9:4033]) by smtp.gmail.com with ESMTPSA id c5-20020a6566c5000000b0056428865aadsm9145378pgw.82.2023.09.05.19.41.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Sep 2023 19:41:07 -0700 (PDT) From: AKASHI Takahiro To: u-boot@lists.denx.de Cc: etienne.carriere@st.com, michal.simek@amd.com, sjg@chromium.org, linus.walleij@linaro.org, Oleksii_Moisieiev@epam.com, AKASHI Takahiro Subject: [RFC 5/6] firmware: scmi: add pseudo pinctrl protocol support on sandbox Date: Wed, 6 Sep 2023 11:40:10 +0900 Message-Id: <20230906024011.17488-6-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230906024011.17488-1-takahiro.akashi@linaro.org> References: <20230906024011.17488-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean With this patch, sandbox SCMI agent can handle pinctrl protocol. This feature is used in an unit test for SCMI pinctrl. Signed-off-by: AKASHI Takahiro --- arch/sandbox/dts/test.dts | 115 ++++ drivers/firmware/scmi/sandbox-scmi_agent.c | 722 +++++++++++++++++++++ 2 files changed, 837 insertions(+) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index dc0bfdfb6e4b..d2ddea801995 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -723,9 +723,124 @@ }; }; }; + + pinctrl_scmi: protocol@19 { + reg = <0x19>; + + pinctrl-names = "default","alternate"; + pinctrl-0 = <&scmi_pinctrl_gpios>, <&scmi_pinctrl_i2s>; + pinctrl-1 = <&scmi_pinctrl_spi>, <&scmi_pinctrl_i2c>; + +#if 0 + scmi_pinctrl_gpio_a: scmi_gpios { + gpio-controller; + #gpio-cells = <2>; + gpio-bank-name = "scmi_gpios"; + ngpios = <4>; + gpio-ranges = <&pinctrl_scmi 0 5 4>, + <&pinctrl_scmi 4 0 0>; + gpio-ranges-group-names = "", + "GPIO_B"; + + hog_input_1 { + gpio-hog; + input; + gpios = <1 GPIO_ACTIVE_HIGH>; + }; + hog_output_3 { + gpio-hog; + output-high; + output-mode; + output-value = <1>; + gpios = <3 GPIO_ACTIVE_HIGH>; + }; + }; +#endif + + scmi_pinctrl_gpios: gpios-pins { + gpio0 { + pins = "P5"; + function = "GPIO"; + bias-pull-up; + // input-disable; + input-mode = <0>; + }; + gpio1 { + pins = "P6"; + function = "GPIO"; + // output-high; + output-mode; + output-value = <1>; + drive-open-drain; + }; + gpio2 { + pinmux = ; + bias-pull-down; + // input-enable; + input-mode; + }; + gpio3 { + pinmux = ; + bias-disable; + }; + }; + + scmi_pinctrl_i2c: i2c-pins { + groups { + groups = "I2C_UART"; + function = "I2C"; + }; + + pins { + pins = "P0", "P1"; + drive-open-drain; + }; + }; + + scmi_pinctrl_i2s: i2s-pins { + groups = "SPI_I2S"; + function = "I2S"; + }; + + scmi_pinctrl_spi: spi-pins { + groups = "SPI_I2S"; + function = "SPI"; + + cs { + pinmux = , + ; + }; + }; + }; }; }; +#if 1 + scmi_pinctrl_gpio_a: scmi_gpios { + compatible = "arm,scmi-gpio-generic"; + gpio-controller; + #gpio-cells = <2>; + gpio-bank-name = "scmi_gpios"; + gpio-ranges = <&pinctrl_scmi 0 5 4>, + <&pinctrl_scmi 4 0 0>; + gpio-ranges-group-names = "", + "GPIO_B"; + + hog_input_1 { + gpio-hog; + input; + gpios = <1 GPIO_ACTIVE_HIGH>; + }; + hog_output_3 { + gpio-hog; + output-high; + output-mode; + output-value = <1>; + gpios = <3 GPIO_ACTIVE_HIGH>; + }; + }; +#endif + fpga { compatible = "sandbox,fpga"; }; diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c index 27d17809be43..d5ff8a2b1c79 100644 --- a/drivers/firmware/scmi/sandbox-scmi_agent.c +++ b/drivers/firmware/scmi/sandbox-scmi_agent.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -43,8 +44,11 @@ #define SANDBOX_SCMI_AGENT_NAME "OSPM" #define SANDBOX_SCMI_PLATFORM_NAME "platform" +#define SANDBOX_SCMI_PIN_CONTROL_PROTOCOL_VERSION SCMI_PIN_CONTROL_PROTOCOL_VERSION + static u8 protocols[] = { SCMI_PROTOCOL_ID_CLOCK, + SCMI_PROTOCOL_ID_PIN_CONTROL, SCMI_PROTOCOL_ID_RESET_DOMAIN, SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN, }; @@ -796,6 +800,696 @@ static int sandbox_scmi_voltd_level_get(struct udevice *dev, return 0; } +/* Pin control protocol */ + +/* + * This driver emulates a pin controller with the following rules: + * - The pinctrl config for each pin must be set individually + * - The first two pins (P0-P1) must be muxed as a group + * - The next three pins (P2-P4) must be muxed as a group + * - The next four pins (P5-P8) must be muxed individually + * - The last two pins (P9-P10) must be fixed as a GPIO group only + + P0: "UART TX", "I2C SCL" + P1: "UART RX", "I2C SDA" + P2: "SPI SCLK", "I2S SCK" + P3: "SPI MOSI", "I2S SD" + P4: "SPI MISO", "I2S WS" + P5: "GPIO0", "SPI CS0" + P6: "GPIO1", "SPI CS1" + P7: "GPIO2", "PWM0" + P8: "GPIO3", "PWM1" + P9: "GPIO_B" + P10: "GPIO_B" + + */ + +static const char * const sandbox_pins[] = { +#define PIN(x) \ + [x] = "P" #x + PIN(0), + PIN(1), + PIN(2), + PIN(3), + PIN(4), + PIN(5), + PIN(6), + PIN(7), + PIN(8), + PIN(9), + PIN(10), +#undef PIN +}; + +static unsigned int sandbox_pin_functions[9]; +static u32 sandbox_pin_states[9][SCMI_PINCTRL_CONFIG_RESERVED]; + +#define SANDBOX_GROUP_I2C_UART 0 +#define SANDBOX_GROUP_SPI_I2S 1 +#define SANDBOX_GROUP_GPIO_B 2 + +static const char * const sandbox_groups[] = { + /* P0-P1 */ + [SANDBOX_GROUP_I2C_UART] = "I2C_UART", + /* P2-P4 */ + [SANDBOX_GROUP_SPI_I2S] = "SPI_I2S", + /* P9-P10 */ + [SANDBOX_GROUP_GPIO_B] = "GPIO_B", +}; + +static const char * const sandbox_functions[] = { +#define FUNC(id) \ + [SANDBOX_PINMUX_##id] = #id + FUNC(UART), + FUNC(I2C), + FUNC(SPI), + FUNC(I2S), + FUNC(GPIO), + FUNC(CS), + FUNC(PWM), + /* FUNC(GPIO_B) */ +#undef FUNC +}; + +static int sandbox_scmi_pinctrl_protocol_version(struct udevice *dev, + struct scmi_msg *msg) +{ + struct scmi_protocol_version_out *out = NULL; + + if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) + return -EINVAL; + + out = (struct scmi_protocol_version_out *)msg->out_msg; + out->version = SANDBOX_SCMI_PIN_CONTROL_PROTOCOL_VERSION; + out->status = SCMI_SUCCESS; + + return 0; +} + +static int sandbox_scmi_pinctrl_protocol_attrs(struct udevice *dev, + struct scmi_msg *msg) +{ + struct scmi_pinctrl_protocol_attrs_out *out = NULL; + + if (!msg->out_msg || msg->out_msg_sz < sizeof(*out)) + return -EINVAL; + + out = (struct scmi_pinctrl_protocol_attrs_out *)msg->out_msg; + out->attributes_low = (ARRAY_SIZE(sandbox_groups) << 16) + + ARRAY_SIZE(sandbox_pins); + out->attributes_high = ARRAY_SIZE(sandbox_functions); + out->status = SCMI_SUCCESS; + + return 0; +} + +static int sandbox_scmi_pinctrl_attrs(struct udevice *dev, + struct scmi_msg *msg) +{ + struct scmi_pinctrl_attrs_in *in; + struct scmi_pinctrl_attrs_out *out; + + if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || + !msg->out_msg || msg->out_msg_sz < sizeof(*out)) + return -EINVAL; + + in = (struct scmi_pinctrl_attrs_in *)msg->in_msg; + out = (struct scmi_pinctrl_attrs_out *)msg->out_msg; + + /* + * Currently all pins have a name with less than 16 characters + * (SCMI_PINCTRL_NAME_LENGTH_MAX). + */ + switch (SCMI_PINCTRL_TYPE(in->flags)) { + case SCMI_PINCTRL_TYPE_PIN: + if (in->id < ARRAY_SIZE(sandbox_pins)) { + strcpy(out->name, sandbox_pins[in->id]); + out->attributes = 0; + } else { + out->status = SCMI_NOT_FOUND; + goto err; + } + break; + case SCMI_PINCTRL_TYPE_GROUP: + if (in->id < ARRAY_SIZE(sandbox_groups)) { + strcpy(out->name, sandbox_groups[in->id]); + out->attributes = in->id ? 3 : 2; + } else { + out->status = SCMI_NOT_FOUND; + goto err; + } + break; + case SCMI_PINCTRL_TYPE_FUNCTION: + if (in->id < ARRAY_SIZE(sandbox_functions)) { + strcpy(out->name, sandbox_functions[in->id]); + if (in->id == 4) /* UART */ + out->attributes = 4; + else if (in->id == 5 || in->id == 6) /* CS or PWM */ + out->attributes = 2; + else + out->attributes = 1; + } else { + out->status = SCMI_NOT_FOUND; + goto err; + } + break; + default: + out->status = SCMI_INVALID_PARAMETERS; + goto err; + } + + out->status = SCMI_SUCCESS; + +err: + return 0; +} + +static int sandbox_scmi_pinctrl_list_assocs(struct udevice *dev, + struct scmi_msg *msg) +{ + struct scmi_pinctrl_list_assocs_in *in; + struct scmi_pinctrl_list_assocs_out *out; + + if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || + !msg->out_msg || msg->out_msg_sz < sizeof(*out)) + return -EINVAL; + + in = (struct scmi_pinctrl_list_assocs_in *)msg->in_msg; + out = (struct scmi_pinctrl_list_assocs_out *)msg->out_msg; + + /* + * UART -> GROUP0 + * I2C -> GROUP0 + * SPI -> GROUP1 + * I2S -> GROUP1 + * GPIO -> PIN5, 6, 7, 8 + * CS -> PIN5, 6 + * PWM -> PIN7, 8 + * (GPIO_B -> GROUP2) + */ + switch (SCMI_PINCTRL_TYPE(in->flags)) { + case SCMI_PINCTRL_TYPE_GROUP: + if (in->id == SANDBOX_GROUP_I2C_UART) { + if (in->index == 0) { + out->array[0] = 0; + out->array[1] = 1; + out->flags = 2; + } else if (in->index == 1) { + out->array[0] = 0; + out->flags = 1; + } else { + out->status = SCMI_OUT_OF_RANGE; + goto err; + } + } else if (in->id == SANDBOX_GROUP_SPI_I2S) { + if (in->index == 0) { + out->array[0] = 2; + out->array[1] = 3; + out->array[2] = 4; + out->flags = 3; + } else if (in->index == 1) { + out->array[0] = 3; + out->array[1] = 4; + out->flags = 2; + } else if (in->index == 2) { + out->array[0] = 4; + out->flags = 1; + } else { + out->status = SCMI_OUT_OF_RANGE; + goto err; + } + } else if (in->id == SANDBOX_GROUP_GPIO_B) { + if (in->index == 0) { + out->array[0] = 9; + out->array[1] = 10; + out->flags = 2; + } else if (in->index == 1) { + out->array[0] = 10; + out->flags = 1; + } else { + out->status = SCMI_OUT_OF_RANGE; + goto err; + } + } else { + out->status = SCMI_NOT_FOUND; + goto err; + } + break; + case SCMI_PINCTRL_TYPE_FUNCTION: + if (in->id == SANDBOX_PINMUX_UART) { + if (in->index > 0) { + out->status = SCMI_OUT_OF_RANGE; + goto err; + } + out->array[0] = SANDBOX_GROUP_I2C_UART; + out->flags = 1; + } else if (in->id == SANDBOX_PINMUX_I2C) { + if (in->index > 0) { + out->status = SCMI_OUT_OF_RANGE; + goto err; + } + out->array[0] = SANDBOX_GROUP_I2C_UART; + out->flags = 1; + } else if (in->id == SANDBOX_PINMUX_SPI) { + if (in->index > 0) { + out->status = SCMI_OUT_OF_RANGE; + goto err; + } + out->array[0] = SANDBOX_GROUP_SPI_I2S; + out->flags = 1; + } else if (in->id == SANDBOX_PINMUX_I2S) { + if (in->index > 0) { + out->status = SCMI_OUT_OF_RANGE; + goto err; + } + out->array[0] = SANDBOX_GROUP_SPI_I2S; + out->flags = 1; + } else { + out->status = SCMI_NOT_FOUND; + goto err; + } + break; + default: + out->status = SCMI_INVALID_PARAMETERS; + goto err; + } + + out->status = SCMI_SUCCESS; + +err: + return 0; +} + +static void copy_config(struct scmi_pin_entry *configs, u32 selector, int skip, + u32 *num, u32 *remaining) +{ + int max_num, i; + + if ((skip + SCMI_PINCTRL_CONFIG_ENTRY_MAX) + > SCMI_PINCTRL_CONFIG_RESERVED) + max_num = SCMI_PINCTRL_CONFIG_RESERVED - skip; + else + max_num = SCMI_PINCTRL_CONFIG_ENTRY_MAX; + + /* TODO: eliminate disabled properties? */ + for (i = 0; i < max_num; i++) { + configs[i].type = skip + i; + configs[i].value = sandbox_pin_states[selector][skip + i]; + } + + *num = max_num; + *remaining = SCMI_PINCTRL_CONFIG_RESERVED - (skip + max_num); +} + +static int sandbox_scmi_pinctrl_config_get(struct udevice *dev, + struct scmi_msg *msg) +{ + struct scmi_pinctrl_config_get_in *in; + struct scmi_pinctrl_config_get_out *out; + u32 type, num, remaining; + int all_configs, skip; + + if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || + !msg->out_msg || msg->out_msg_sz < sizeof(*out)) + return -EINVAL; + + in = (struct scmi_pinctrl_config_get_in *)msg->in_msg; + out = (struct scmi_pinctrl_config_get_out *)msg->out_msg; + + all_configs = in->attributes & SCMI_PINCTRL_CONFIG_GET_ALL; + skip = SCMI_PINCTRL_CONFIG_GET_SKIP(in->attributes); + type = SCMI_PINCTRL_CONFIG_GET_TYPE(in->attributes); + if (type >= SCMI_PINCTRL_CONFIG_RESERVED) { + out->status = SCMI_INVALID_PARAMETERS; + goto err; + } + + switch (SCMI_PINCTRL_CONFIG_GET_PINCTRL_TYPE(in->attributes)) { + case SCMI_PINCTRL_TYPE_PIN: + if (in->id < ARRAY_SIZE(sandbox_pins)) { + if (all_configs) { + if (skip >= SCMI_PINCTRL_CONFIG_RESERVED) { + out->status = SCMI_INVALID_PARAMETERS; + goto err; + } + num = 0; /* avoid compiler warning */ + remaining = 0; + copy_config(&out->configs[0], in->id, skip, + &num, &remaining); + } else { + out->configs[0].type = type; + out->configs[0].value = + sandbox_pin_states[in->id][type]; + num = 1; + remaining = 0; + } + } else { + out->status = SCMI_NOT_FOUND; + goto err; + } + out->num_configs = + SCMI_PINCTRL_CONFIG_GET_NUM_CONFIGS(remaining, num); + break; + case SCMI_PINCTRL_TYPE_GROUP: + if (in->id < ARRAY_SIZE(sandbox_groups)) { + /* TODO */; + } else { + out->status = SCMI_NOT_FOUND; + goto err; + } + break; + default: + out->status = SCMI_INVALID_PARAMETERS; + goto err; + } + + out->status = SCMI_SUCCESS; + +err: + return 0; +} + +static int sandbox_scmi_pinctrl_config_set(struct udevice *dev, + struct scmi_msg *msg) +{ + struct scmi_pinctrl_config_set_in *in; + u32 *status; + int i, num; + + if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || + !msg->out_msg || msg->out_msg_sz < sizeof(*status)) + return -EINVAL; + + in = (struct scmi_pinctrl_config_set_in *)msg->in_msg; + status = (u32 *)msg->out_msg; + + num = SCMI_PINCTRL_CONFIG_SET_NUM_CONFIGS(in->attributes); + if (num > SCMI_PINCTRL_CONFIG_ENTRY_MAX) { + *status = SCMI_PROTOCOL_ERROR; + goto err; + } + + switch (SCMI_PINCTRL_CONFIG_SET_PINCTRL_TYPE(in->attributes)) { + case SCMI_PINCTRL_TYPE_PIN: + if (in->id < ARRAY_SIZE(sandbox_pins)) { + /* TODO: check value range */ + for (i = 0; i < num; i++) + sandbox_pin_states[in->id][in->configs[i].type] + = in->configs[i].value; + } else { + *status = SCMI_NOT_FOUND; + goto err; + } + break; + case SCMI_PINCTRL_TYPE_GROUP: + /* TODO: check value range */ + if (!in->id) { + for (i = 0; i < num; i++) { + sandbox_pin_states[0][in->configs[i].type] = + in->configs[i].value; + sandbox_pin_states[1][in->configs[i].type] = + in->configs[i].value; + } + } else if (in->id == 1) { + for (i = 0; i < num; i++) { + sandbox_pin_states[2][in->configs[i].type] = + in->configs[i].value; + sandbox_pin_states[3][in->configs[i].type] = + in->configs[i].value; + sandbox_pin_states[4][in->configs[i].type] = + in->configs[i].value; + } + } else if (in->id == 2) { + for (i = 0; i < num; i++) { + sandbox_pin_states[9][in->configs[i].type] = + in->configs[i].value; + sandbox_pin_states[10][in->configs[i].type] = + in->configs[i].value; + } + } else { + *status = SCMI_NOT_FOUND; + goto err; + } + break; + default: + *status = SCMI_INVALID_PARAMETERS; + goto err; + } + + *status = SCMI_SUCCESS; +err: + return 0; +} + +static int sandbox_scmi_pinctrl_function_select(struct udevice *dev, + struct scmi_msg *msg) +{ + struct scmi_pinctrl_function_select_in *in; + u32 *status; + + if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || + !msg->out_msg || msg->out_msg_sz < sizeof(*status)) + return -EINVAL; + + in = (struct scmi_pinctrl_function_select_in *)msg->in_msg; + status = (u32 *)msg->out_msg; + + switch (SCMI_PINCTRL_TYPE(in->flags)) { + case SCMI_PINCTRL_TYPE_PIN: + if (in->id == 5 || in->id == 6) { + if (in->function_id == SANDBOX_PINMUX_GPIO || + in->function_id == SANDBOX_PINMUX_CS) { + sandbox_pin_functions[in->id] = in->function_id; + *status = SCMI_SUCCESS; + } else { + *status = SCMI_NOT_SUPPORTED; + } + } else if (in->id == 7 || in->id == 8) { + if (in->function_id == SANDBOX_PINMUX_GPIO || + in->function_id == SANDBOX_PINMUX_PWM) { + sandbox_pin_functions[in->id] = in->function_id; + *status = SCMI_SUCCESS; + } else { + *status = SCMI_NOT_SUPPORTED; + } + } + break; + case SCMI_PINCTRL_TYPE_GROUP: + if (in->id == SANDBOX_GROUP_I2C_UART) { + if (in->function_id == SANDBOX_PINMUX_UART || + in->function_id == SANDBOX_PINMUX_I2C) { + sandbox_pin_functions[0] = in->function_id; + sandbox_pin_functions[1] = in->function_id; + *status = SCMI_SUCCESS; + } else { + *status = SCMI_NOT_SUPPORTED; + } + } else if (in->id == SANDBOX_GROUP_SPI_I2S) { + if (in->function_id == SANDBOX_PINMUX_SPI || + in->function_id == SANDBOX_PINMUX_I2S) { + sandbox_pin_functions[2] = in->function_id; + sandbox_pin_functions[3] = in->function_id; + sandbox_pin_functions[4] = in->function_id; + *status = SCMI_SUCCESS; + } else { + *status = SCMI_NOT_SUPPORTED; + } + } + break; + default: + *status = SCMI_INVALID_PARAMETERS; + goto err; + } + + *status = SCMI_SUCCESS; +err: + return 0; +} + +static int sandbox_scmi_pinctrl_request(struct udevice *dev, + struct scmi_msg *msg) +{ + struct scmi_pinctrl_request_in *in; + u32 *status; + + if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || + !msg->out_msg || msg->out_msg_sz < sizeof(*status)) + return -EINVAL; + + in = (struct scmi_pinctrl_request_in *)msg->in_msg; + status = (u32 *)msg->out_msg; + + /* + * No other agent, so always accept the request + */ + switch (SCMI_PINCTRL_TYPE(in->flags)) { + case SCMI_PINCTRL_TYPE_PIN: + if (in->id >= ARRAY_SIZE(sandbox_pins)) { + *status = SCMI_NOT_FOUND; + goto err; + } + break; + case SCMI_PINCTRL_TYPE_GROUP: + if (in->id >= ARRAY_SIZE(sandbox_groups)) { + *status = SCMI_NOT_FOUND; + goto err; + } + break; + default: + *status = SCMI_INVALID_PARAMETERS; + goto err; + } + + *status = SCMI_SUCCESS; +err: + return 0; +} + +static int sandbox_scmi_pinctrl_release(struct udevice *dev, + struct scmi_msg *msg) +{ + struct scmi_pinctrl_release_in *in; + u32 *status; + + if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || + !msg->out_msg || msg->out_msg_sz < sizeof(*status)) + return -EINVAL; + + in = (struct scmi_pinctrl_release_in *)msg->in_msg; + status = (u32 *)msg->out_msg; + + /* + * No other agent, so always accept the release + */ + switch (SCMI_PINCTRL_TYPE(in->flags)) { + case SCMI_PINCTRL_TYPE_PIN: + if (in->id >= ARRAY_SIZE(sandbox_pins)) { + *status = SCMI_NOT_FOUND; + goto err; + } + break; + case SCMI_PINCTRL_TYPE_GROUP: + if (in->id >= ARRAY_SIZE(sandbox_groups)) { + *status = SCMI_NOT_FOUND; + goto err; + } + break; + default: + *status = SCMI_INVALID_PARAMETERS; + goto err; + } + + *status = SCMI_SUCCESS; +err: + return 0; +} + +static int sandbox_scmi_pinctrl_name_get(struct udevice *dev, + struct scmi_msg *msg) +{ + struct scmi_pinctrl_name_get_in *in; + struct scmi_pinctrl_name_get_out *out; + + if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || + !msg->out_msg || msg->out_msg_sz < sizeof(*out)) + return -EINVAL; + + in = (struct scmi_pinctrl_name_get_in *)msg->in_msg; + out = (struct scmi_pinctrl_name_get_out *)msg->out_msg; + + /* + * Currently all pins have a name with less than 64 characters + */ + switch (SCMI_PINCTRL_TYPE(in->flags)) { + case SCMI_PINCTRL_TYPE_PIN: + if (in->id < ARRAY_SIZE(sandbox_pins)) { + strcpy(out->name, sandbox_pins[in->id]); + } else { + out->status = SCMI_NOT_FOUND; + goto err; + } + break; + case SCMI_PINCTRL_TYPE_GROUP: + if (in->id < ARRAY_SIZE(sandbox_groups)) { + strcpy(out->name, sandbox_groups[in->id]); + } else { + out->status = SCMI_NOT_FOUND; + goto err; + } + break; + case SCMI_PINCTRL_TYPE_FUNCTION: + if (in->id < ARRAY_SIZE(sandbox_functions)) { + strcpy(out->name, sandbox_functions[in->id]); + } else { + out->status = SCMI_NOT_FOUND; + goto err; + } + break; + default: + out->status = SCMI_INVALID_PARAMETERS; + goto err; + } + + out->flags = 0; + out->status = SCMI_SUCCESS; + +err: + return 0; +} + +static int sandbox_scmi_pinctrl_set_permissions(struct udevice *dev, + struct scmi_msg *msg) +{ + struct scmi_pinctrl_set_permissions_in *in; + u32 *status; + + if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) || + !msg->out_msg || msg->out_msg_sz < sizeof(*status)) + return -EINVAL; + + in = (struct scmi_pinctrl_set_permissions_in *)msg->in_msg; + status = (u32 *)msg->out_msg; + + if (in->agent_id != 1) { + *status = SCMI_NOT_FOUND; + goto err; + } + + switch (SCMI_PINCTRL_TYPE(in->flags)) { + case SCMI_PINCTRL_TYPE_PIN: + if (in->id < ARRAY_SIZE(sandbox_pins)) { + if (in->flags & SCMI_PINCTRL_PERMISSION) + *status = SCMI_SUCCESS; + else + /* unset not allowed */ + *status = SCMI_DENIED; + } else { + *status = SCMI_NOT_FOUND; + goto err; + } + break; + case SCMI_PINCTRL_TYPE_GROUP: + if (in->id < ARRAY_SIZE(sandbox_groups)) { + if (in->flags & SCMI_PINCTRL_PERMISSION) + *status = SCMI_SUCCESS; + else + /* unset not allowed */ + *status = SCMI_DENIED; + } else { + *status = SCMI_NOT_FOUND; + goto err; + } + break; + default: + *status = SCMI_INVALID_PARAMETERS; + goto err; + } + + *status = SCMI_SUCCESS; +err: + return 0; +} + static int sandbox_scmi_test_process_msg(struct udevice *dev, struct scmi_channel *channel, struct scmi_msg *msg) @@ -847,6 +1541,34 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, break; } break; + case SCMI_PROTOCOL_ID_PIN_CONTROL: + switch (msg->message_id) { + case SCMI_PROTOCOL_VERSION: + return sandbox_scmi_pinctrl_protocol_version(dev, msg); + case SCMI_PROTOCOL_ATTRIBUTES: + return sandbox_scmi_pinctrl_protocol_attrs(dev, msg); + case SCMI_PINCTRL_ATTRIBUTES: + return sandbox_scmi_pinctrl_attrs(dev, msg); + case SCMI_PINCTRL_LIST_ASSOCIATIONS: + return sandbox_scmi_pinctrl_list_assocs(dev, msg); + case SCMI_PINCTRL_CONFIG_GET: + return sandbox_scmi_pinctrl_config_get(dev, msg); + case SCMI_PINCTRL_CONFIG_SET: + return sandbox_scmi_pinctrl_config_set(dev, msg); + case SCMI_PINCTRL_FUNCTION_SELECT: + return sandbox_scmi_pinctrl_function_select(dev, msg); + case SCMI_PINCTRL_REQUEST: + return sandbox_scmi_pinctrl_request(dev, msg); + case SCMI_PINCTRL_RELEASE: + return sandbox_scmi_pinctrl_release(dev, msg); + case SCMI_PINCTRL_NAME_GET: + return sandbox_scmi_pinctrl_name_get(dev, msg); + case SCMI_PINCTRL_SET_PERMISSIONS: + return sandbox_scmi_pinctrl_set_permissions(dev, msg); + default: + break; + } + break; case SCMI_PROTOCOL_ID_RESET_DOMAIN: switch (msg->message_id) { case SCMI_RESET_DOMAIN_ATTRIBUTES: From patchwork Wed Sep 6 02:40:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 720401 Delivered-To: patch@linaro.org Received: by 2002:adf:d08b:0:b0:31d:da82:a3b4 with SMTP id y11csp2461753wrh; Tue, 5 Sep 2023 19:42:08 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFg5setiNBYyU5hL4MDUWMev5Doc6k++NeUqzW7JvGZZY8mbY4ALBpxp9UqJzfbbQuWqTC7 X-Received: by 2002:a5d:504b:0:b0:319:7428:9ca0 with SMTP id h11-20020a5d504b000000b0031974289ca0mr163682wrt.61.1693968128458; Tue, 05 Sep 2023 19:42:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1693968128; cv=none; d=google.com; s=arc-20160816; b=juYMf6TOwA+PR6oO/NdEQbOuHzwyxbZcmkL0r/inmszAVO+3Mv+Iy7i+0cAtgebv/r S07TbluIEoznvXMx5MXpJdLTLHi1a7qWuAludXlrWuwOp/meK5Bxka//YFVMQMIVbcCR v04RBbFzn3p4v7nwjSF3VmCMdSyZ9Gi7112BjizU87H3ctgfYPcH7lJYlOoPkGeV+Rsb wXDMNz3P5TDNRlkqTeRoX4GIpepifwcVMSgTDK8EqUFBg/8G5UfGmMTYHLIAwkjltIq6 qPAcNPBxGF7BAwZX5+ZlAOrNO3Vt8bpaQG/4eU18IrMru7F563NB2gjeb2Mjeu6Pvpsz YM5Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=Qbtfx7u6KwcO2aMHhHr2Q6+3/YafCKFjaH7opDRFSf0=; fh=Yz321xYbZlOZFLAVVWewQ+h9487s8fAdGcGeu++kLX8=; b=TvuYDG9i7oA+TXmHLfkPyrhdAZgcKGKSAb86RrShUMiaOFPjaC/3VRqjU2yiboWBXx iIG9iv0brGryw7zdVwPR/JZpwsm1zgxMLm4tlEstisiYyH3PIbE3DAYLuXwiM8UkDacO d/akiPEi3iPtcZDzPW2omTx2nGjCxphD9ml5LIHqeX/iSp8Fx2SxZL/sU1hf6oskaE85 Dny0BY/grtdILyKC6c4Yw1s0gD4PIe13AqGG3HoQbUedlRG44xleg8BxA8+bs4B90Rwd boj6uhgfJZI7gBWz0ydOU10ZVtrLnuZON6WGiWZc/casiJLafQkCCalE/aY1g9ieC55h kuHA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="YQg/F1jV"; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id r2-20020adff102000000b003176b4934basi6379387wro.842.2023.09.05.19.42.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Sep 2023 19:42:08 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="YQg/F1jV"; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 495878698F; Wed, 6 Sep 2023 04:41:16 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="YQg/F1jV"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id E28DD865A8; Wed, 6 Sep 2023 04:41:14 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pf1-x436.google.com (mail-pf1-x436.google.com [IPv6:2607:f8b0:4864:20::436]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 97213866DC for ; Wed, 6 Sep 2023 04:41:11 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=takahiro.akashi@linaro.org Received: by mail-pf1-x436.google.com with SMTP id d2e1a72fcca58-68a32506e90so700526b3a.1 for ; Tue, 05 Sep 2023 19:41:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1693968070; x=1694572870; darn=lists.denx.de; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Qbtfx7u6KwcO2aMHhHr2Q6+3/YafCKFjaH7opDRFSf0=; b=YQg/F1jV9aobNwpMa0DApqSO4exusX6/Z8hmLX6hUmQdgLWyFTLaEQU2b+c9rgJCoh UaYD4vzc2DhPdJ8/QUAwQ6W/O69VhWsrTY1hoSmgSUPs2Hhqwxm3gGfGxrUloqY13ldk p8zR7TzVb+EIOKTKev+zZQLG6oGaK0jb1R/df53ykH0GL2lxO7qX4Tg+ZoLPVLbjbMmf PaZOiE/KZK+wVRHadD51n8NyUCl9mG2Fgjw5QEjakQ6vAZjkinbNMOm2cg4nZU3h24S5 gAcfuUh030hZXu7Fww26KXR2XcZIH85v/HSh2QeYDBPAYPwOKe0uogzvI8jHFSrqF/xQ JzzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1693968070; x=1694572870; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Qbtfx7u6KwcO2aMHhHr2Q6+3/YafCKFjaH7opDRFSf0=; b=Y1jdr0USUi/4aIJd3OUbgHSVc/ImbV1VMqrBMoMq1pEZAfWuQd7jf+YogMrBcEG6hV SFoYFQv4lo2BtJCAfHqB80cTPDRyX/oN0OSbgRTHB0rItUcSnAXbFgtRM1cgfBeHk2cn ws7N28qs+py/XmK64GY/d/c7YmolA7z4SDiwxIPp0fPhBnGdH4dDXoHAZVzH3foZejJt +AZr/FOodlIrzU0DE3jl7kkz0erH9QJtvnaTenVEZNbhv6b9FZHKvnk+s7qpJunsketv gl/an+xWOI9D8r9ti8wON1ZXKB5fgYPXoD51XI09FqMlskBP7kZwdBnV9iaECkByjBoY mP8g== X-Gm-Message-State: AOJu0Yw99DYk2gyzmj9IoZRYRgT76RUVQdj0XXMvs2cc0zz0MfEGdhyq UC70AP3IeAciNRHxVVXOt4rER/cOzZFt47Vq2sPJeA== X-Received: by 2002:a05:6a00:f0e:b0:68b:c562:da46 with SMTP id cr14-20020a056a000f0e00b0068bc562da46mr16015519pfb.1.1693968069848; Tue, 05 Sep 2023 19:41:09 -0700 (PDT) Received: from octopus.. ([2400:4050:c3e1:100:8294:a07d:b7e9:4033]) by smtp.gmail.com with ESMTPSA id c5-20020a6566c5000000b0056428865aadsm9145378pgw.82.2023.09.05.19.41.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Sep 2023 19:41:09 -0700 (PDT) From: AKASHI Takahiro To: u-boot@lists.denx.de Cc: etienne.carriere@st.com, michal.simek@amd.com, sjg@chromium.org, linus.walleij@linaro.org, Oleksii_Moisieiev@epam.com, AKASHI Takahiro Subject: [RFC 6/6] test: dm: add SCMI pinctrl test Date: Wed, 6 Sep 2023 11:40:11 +0900 Message-Id: <20230906024011.17488-7-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230906024011.17488-1-takahiro.akashi@linaro.org> References: <20230906024011.17488-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.8 at phobos.denx.de X-Virus-Status: Clean In this test, SCMI-based pinmux feature is exercised. Signed-off-by: AKASHI Takahiro --- test/dm/scmi.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/test/dm/scmi.c b/test/dm/scmi.c index 423b6ef70b29..ca5a2e9c781e 100644 --- a/test/dm/scmi.c +++ b/test/dm/scmi.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -395,3 +396,64 @@ static int dm_test_scmi_voltage_domains(struct unit_test_state *uts) return release_sandbox_scmi_test_devices(uts, dev); } DM_TEST(dm_test_scmi_voltage_domains, UT_TESTF_SCAN_FDT); + +/* + * This part is derived from test/dm/pinmux.c, So + * + * Copyright (C) 2020 Sean Anderson + */ + +static char buf[64]; +#define test_muxing(selector, expected) do { \ + ut_assertok(pinctrl_get_pin_muxing(dev, selector, buf, sizeof(buf))); \ + ut_asserteq_str(expected, (char *)&buf); \ +} while (0) + +#define test_name(selector, expected) do { \ + ut_assertok(pinctrl_get_pin_name(dev, selector, buf, sizeof(buf))); \ + ut_asserteq_str(expected, (char *)&buf); \ +} while (0) + +static int dm_test_scmi_pinmux(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_get_device_by_name(UCLASS_PINCTRL, "protocol@19", + &dev)); + ut_assertok(pinctrl_select_state(dev, "default")); + test_muxing(0, ""); + test_muxing(1, ""); + test_muxing(2, "I2S."); + test_muxing(3, "I2S."); + test_muxing(4, "I2S."); + test_muxing(5, "GPIO bias-pull-up."); + test_muxing(6, "GPIO drive-open-drain output-mode output-value."); + test_muxing(7, "GPIO bias-pull-down input-mode."); + test_muxing(8, "GPIO bias-disable."); + + ut_assertok(pinctrl_select_state(dev, "alternate")); + test_muxing(0, "I2C drive-open-drain."); + test_muxing(1, "I2C drive-open-drain."); + test_muxing(2, "SPI."); + test_muxing(3, "SPI."); + test_muxing(4, "SPI."); + test_muxing(5, "CS bias-pull-up."); + test_muxing(6, "CS drive-open-drain output-mode output-value."); + test_muxing(7, "GPIO bias-pull-down input-mode."); + test_muxing(8, "GPIO bias-disable."); + + ut_assertok(pinctrl_select_state(dev, "0")); + test_muxing(0, "I2C drive-open-drain."); + test_muxing(1, "I2C drive-open-drain."); + test_muxing(2, "I2S."); + test_muxing(3, "I2S."); + test_muxing(4, "I2S."); + test_muxing(5, "GPIO bias-pull-up."); + test_muxing(6, "GPIO drive-open-drain output-mode output-value."); + test_muxing(7, "GPIO bias-pull-down input-mode."); + test_muxing(8, "GPIO bias-disable."); + + return 0; +} + +DM_TEST(dm_test_scmi_pinmux, UT_TESTF_SCAN_FDT);