Received: by 2002:a25:f815:0:0:0:0:0 with SMTP id u21csp2776699ybd; Thu, 27 Jun 2019 19:40:57 -0700 (PDT) X-Google-Smtp-Source: APXvYqzfXEwMfJkUZkZH4WB3aX5iyfsGPY2i2Br/cPx2YTCPkOVdKq/fdgkQvrwXq0wkPvZYCdoX X-Received: by 2002:a17:902:868f:: with SMTP id g15mr8511207plo.67.1561689657044; Thu, 27 Jun 2019 19:40:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1561689657; cv=none; d=google.com; s=arc-20160816; b=NH1yrZdGxKjLNMyw2KGv4vkruhYgN+iVdjwOE6lyc/zujrA/OFOen8jH+ojKPd9TBT N6BtlGMl97iTDpdRDjSuObSoLsDsbUYV0+oII45YeElcnBDm0so4W40WZTIwi0duxY5o otBWdaFVxCfBWLLnh1gq3BYStliLYPW0ydok1MGGslA6sCLJgsjOOmC3Bi2MYplrMUEn whoACkQmLnWGVRkowunzw+WYRdIoslXoP4Wm6jFCGWwZqFqOAUnTbXA5Ds9rbuaasoOa 1Y8DNmBMyFo3lIBYSmg4BWd0QNn6vj4nr6c2zQlkxyQX6I/B3PliOOJLZk9JQwW8HGYw AHdA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature:dkim-signature; bh=MPFfXAMopBJpRZjirOncY4gwnFS+WGjHM5WJUlUs384=; b=F54655v79sjfSMBviQfD3/NA7zdW3AvRpo9v8NyTPQ1qjOdlsqB5AZsL9ZbBWqrHvQ NFIRgZ7U9Yxows8wk1V26Arr+dYWeqJIzReie0WjRkug2709z597dNbRH6YY2pCByw3N xXhJEHQUfp8M12u1qxkq4VDmg9Bw7XHAsoX2cA4tQqCLrFVB95WkMCfxswU/XNlNUJ9S M0oJZYi0vHWIphtifnOGDsZb7IU/W2/xNWuWofBUG0In1KSdQDjFW5DdNS2XuEWUBbG9 P9NPoYRLfzjII/Af19lv5HnlsF3qi6S67TaNNTM5mqCybF7NUK2tOGHDiEgDI0c5O2Mr B9Yg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@aj.id.au header.s=fm3 header.b=AGj08IWZ; dkim=pass header.i=@messagingengine.com header.s=fm3 header.b=ZsB2OOfD; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h3si866310pgv.403.2019.06.27.19.40.41; Thu, 27 Jun 2019 19:40:57 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@aj.id.au header.s=fm3 header.b=AGj08IWZ; dkim=pass header.i=@messagingengine.com header.s=fm3 header.b=ZsB2OOfD; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727084AbfF1Cj5 (ORCPT + 99 others); Thu, 27 Jun 2019 22:39:57 -0400 Received: from new2-smtp.messagingengine.com ([66.111.4.224]:47551 "EHLO new2-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727054AbfF1Cjw (ORCPT ); Thu, 27 Jun 2019 22:39:52 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailnew.nyi.internal (Postfix) with ESMTP id E2CEE2CC1; Thu, 27 Jun 2019 22:39:50 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute4.internal (MEProxy); Thu, 27 Jun 2019 22:39:50 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aj.id.au; h=from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; s=fm3; bh=MPFfXAMopBJpR ZjirOncY4gwnFS+WGjHM5WJUlUs384=; b=AGj08IWZ4q+WD4X2r3GZK+/4U3lio r56CeKOrCH3vhoTjHATI01NjJxvcHPDFygBTNyM7y2UnJu5okOx3e5usgYSmDaIG oay+66a2C3IN0Iq6vqTfD4QjmAUGFZeu0oLjnbJ9jm6RGNjuHCbvwFZvZ7dg3y2s SiyBp1kqwJCohFndwhawCrSkaUMJKgpd7N8mxWJ61W4hA8QMbF1PaciRpGyeq/Tf N1orKJ8Cca9nv9gT5eUaPLUJ/nnb8uNmZdfDCaTQhxdNNzzks4UwJdS0c3G6yqaC R95r8cSleNc//nEsaIlKkYWBgg5iiknhi2+zIVkn6thb17lOzWURtu99w== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:from :in-reply-to:message-id:mime-version:references:subject:to :x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; bh=MPFfXAMopBJpRZjirOncY4gwnFS+WGjHM5WJUlUs384=; b=ZsB2OOfD Y4Z4bkzmXybMoaD3WsbGx6CNdngxCbI1bWfmdQbGSS4+yb+F4zDjvRRQZGpn2Tpx b8X0Y/CcXNjNvQPxT3i8/Qtoz3oKxJV0urUbnVSK0JJ/1dqIR2TGEkQBoicQn4Zo k9LpC4xiBOybGFPa8I1Kz3M5NtOY3VVNC04xiXiKsjlFIiEHR+wlB6HiqM5JBeTk sFLoN0ml9RNCmtKnj90eQBOPOkZm6D/Hwkg6EAqpYxmYb/Htkok7b+74tbAVxgKK dErMZt7ipbKrPRRoE1ZDdDySQsBGSnH2RFG46IpJxx6FdoqEJ6221NU5gbdZpgxJ VwRZ57u4S+5R4Q== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduvddrudelgdeiudcutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpefhvffufffkofgjfhgggfestdekredtredttdenucfhrhhomheptehnughrvgif ucflvghffhgvrhihuceorghnughrvgifsegrjhdrihgurdgruheqnecukfhppedvtddvrd ekuddrudekrdeftdenucfrrghrrghmpehmrghilhhfrhhomheprghnughrvgifsegrjhdr ihgurdgruhenucevlhhushhtvghrufhiiigvpeeg X-ME-Proxy: Received: from mistburn.au.ibm.com (bh02i525f01.au.ibm.com [202.81.18.30]) by mail.messagingengine.com (Postfix) with ESMTPA id A1FA3380075; Thu, 27 Jun 2019 22:39:46 -0400 (EDT) From: Andrew Jeffery To: linux-gpio@vger.kernel.org Cc: ryan_chen@aspeedtech.com, Andrew Jeffery , linus.walleij@linaro.org, robh+dt@kernel.org, mark.rutland@arm.com, joel@jms.id.au, linux-aspeed@lists.ozlabs.org, openbmc@lists.ozlabs.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Johnny Huang Subject: [PATCH v2 8/8] pinctrl: aspeed: Add implementation-related documentation Date: Fri, 28 Jun 2019 12:08:38 +0930 Message-Id: <20190628023838.15426-9-andrew@aj.id.au> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190628023838.15426-1-andrew@aj.id.au> References: <20190628023838.15426-1-andrew@aj.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The ASPEED pinctrl driver implementations make heavy use of macros to minimise tedium of implementation and maximise the chance that the compiler will catch errors in defining signal and pin configurations. While the goal of minimising errors is achieved, it is at the cost of the complexity of the macros. Document examples of the expanded form of pin declarations to demonstrate the operation of the macros. Cc: Johnny Huang Signed-off-by: Andrew Jeffery --- drivers/pinctrl/aspeed/pinmux-aspeed.h | 204 ++++++++++++++++++++++++- 1 file changed, 200 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/aspeed/pinmux-aspeed.h b/drivers/pinctrl/aspeed/pinmux-aspeed.h index a036ce8f1571..329d54d48667 100644 --- a/drivers/pinctrl/aspeed/pinmux-aspeed.h +++ b/drivers/pinctrl/aspeed/pinmux-aspeed.h @@ -18,7 +18,8 @@ * priority level are frequently not the same (i.e. cannot just flip a bit to * change from a high to low priority signal), or even in the same register. * Further, not all signals can be unmuxed, as some expressions depend on - * values in the hardware strapping register (which is treated as read-only). + * values in the hardware strapping register (which may be treated as + * read-only). * * SoC Multi-function Pin Expression Examples * ------------------------------------------ @@ -172,9 +173,9 @@ * * A signal expression is the smallest set of signal descriptors whose * comparisons must evaluate 'true' for a signal to be enabled on a pin. * - * * A function's signal is active on a pin if evaluating all signal - * descriptors in the pin's signal expression for the function yields a 'true' - * result + * * A signal participating in a function is active on a pin if evaluating all + * signal descriptors in the pin's signal expression for the function yields + * a 'true' result * * * A signal at a given priority on a given pin is active if any of the * functions in which the signal participates are active, and no higher @@ -221,6 +222,201 @@ * well as pins) required for the group's configuration will already be in use, * likely in a way that's inconsistent with the requirements of the failed * group. + * + * Implementation + * -------------- + * + * Beyond the documentation below the various structures and helper macros that + * allow the implementation to hang together are defined. The macros are fairly + * dense, so below we walk through some raw examples of the configuration + * tables in an effort to clarify the concepts. + * + * The complexity of configuring the mux combined with the scale of the pins + * and functions was a concern, so the table design along with the macro jungle + * is an attempt to address it. The rough principles of the approach are: + * + * 1. Use a data-driven solution rather than embedding state into code + * 2. Minimise editing to the specifics of the given mux configuration + * 3. Detect as many errors as possible at compile time + * + * Addressing point 3 leads to naming of symbols in terms of the four + * properties associated with a given mux configuration: The pin, the signal, + * the group and the function. In this way copy/paste errors cause duplicate + * symbols to be defined, which prevents successful compilation. Failing to + * properly parent the tables leads to unused symbol warnings, and use of + * designated initialisers and additional warnings ensures that there are + * no override errors in the pin, group and function arrays. + * + * Addressing point 2 drives the development of the macro jungle, as it + * centralises the definition noise at the cost of taking some time to + * understand. + * + * Here's a complete, concrete "pre-processed" example of the table structures + * used to describe the D6 ball from the examples above: + * + * ``` + * static const struct aspeed_sig_desc sig_descs_MAC1LINK_MAC1LINK[] = { + * { + * .ip = ASPEED_IP_SCU, + * .reg = 0x80, + * .mask = BIT(0), + * .enable = 1, + * .disable = 0 + * }, + * }; + * + * static const struct aspeed_sig_expr sig_expr_MAC1LINK_MAC1LINK = { + * .signal = "MAC1LINK", + * .function = "MAC1LINK", + * .ndescs = ARRAY_SIZE(sig_descs_MAC1LINK_MAC1LINK), + * .descs = &(sig_descs_MAC1LINK_MAC1LINK)[0], + * }; + * + * static const struct aspeed_sig_expr *sig_exprs_MAC1LINK_MAC1LINK[] = { + * &sig_expr_MAC1LINK_MAC1LINK, + * NULL, + * }; + * + * static const struct aspeed_sig_desc sig_descs_GPIOA0_GPIOA0[] = { }; + * + * static const struct aspeed_sig_expr sig_expr_GPIOA0_GPIOA0 = { + * .signal = "GPIOA0", + * .function = "GPIOA0", + * .ndescs = ARRAY_SIZE(sig_descs_GPIOA0_GPIOA0), + * .descs = &(sig_descs_GPIOA0_GPIOA0)[0], + * }; + * + * static const struct aspeed_sig_expr *sig_exprs_GPIOA0_GPIOA0[] = { + * &sig_expr_GPIOA0_GPIOA0, + * NULL + * }; + * + * static const struct aspeed_sig_expr **pin_exprs_0[] = { + * sig_exprs_MAC1LINK_MAC1LINK, + * sig_exprs_GPIOA0_GPIOA0, + * NULL + * }; + * + * static const struct aspeed_pin_desc pin_0 = { "0", (&pin_exprs_0[0]) }; + * static const int group_pins_MAC1LINK[] = { 0 }; + * static const char *func_groups_MAC1LINK[] = { "MAC1LINK" }; + * + * static struct pinctrl_pin_desc aspeed_g4_pins[] = { + * [0] = { .number = 0, .name = "D6", .drv_data = &pin_0 }, + * }; + * + * static const struct aspeed_pin_group aspeed_g4_groups[] = { + * { + * .name = "MAC1LINK", + * .pins = &(group_pins_MAC1LINK)[0], + * .npins = ARRAY_SIZE(group_pins_MAC1LINK), + * }, + * }; + * + * static const struct aspeed_pin_function aspeed_g4_functions[] = { + * { + * .name = "MAC1LINK", + * .groups = &func_groups_MAC1LINK[0], + * .ngroups = ARRAY_SIZE(func_groups_MAC1LINK), + * }, + * }; + * ``` + * + * At the end of the day much of the above code is compressed into the + * following two lines: + * + * ``` + * #define D6 0 + * SSSF_PIN_DECL(D6, GPIOA0, MAC1LINK, SIG_DESC_SET(SCU80, 0)); + * ``` + * + * The two examples below show just the differences from the example above. + * + * Ball E18 demonstrates a function, EXTRST, that requires multiple descriptors + * be set for it to be muxed: + * + * ``` + * static const struct aspeed_sig_desc sig_descs_EXTRST_EXTRST[] = { + * { + * .ip = ASPEED_IP_SCU, + * .reg = 0x3C, + * .mask = BIT(3), + * .enable = 1, + * .disable = 0 + * }, + * { + * .ip = ASPEED_IP_SCU, + * .reg = 0x80, + * .mask = BIT(15), + * .enable = 1, + * .disable = 0 + * }, + * { + * .ip = ASPEED_IP_SCU, + * .reg = 0x90, + * .mask = BIT(31), + * .enable = 0, + * .disable = 1 + * }, + * }; + * + * static const struct aspeed_sig_expr sig_expr_EXTRST_EXTRST = { + * .signal = "EXTRST", + * .function = "EXTRST", + * .ndescs = ARRAY_SIZE(sig_descs_EXTRST_EXTRST), + * .descs = &(sig_descs_EXTRST_EXTRST)[0], + * }; + * ... + * ``` + * + * For ball E19, we have multiple functions enabling a single signal, LPCRST#. + * The data structures look like: + * + * static const struct aspeed_sig_desc sig_descs_LPCRST_LPCRST[] = { + * { + * .ip = ASPEED_IP_SCU, + * .reg = 0x80, + * .mask = BIT(12), + * .enable = 1, + * .disable = 0 + * }, + * }; + * + * static const struct aspeed_sig_expr sig_expr_LPCRST_LPCRST = { + * .signal = "LPCRST", + * .function = "LPCRST", + * .ndescs = ARRAY_SIZE(sig_descs_LPCRST_LPCRST), + * .descs = &(sig_descs_LPCRST_LPCRST)[0], + * }; + * + * static const struct aspeed_sig_desc sig_descs_LPCRST_LPCRSTS[] = { + * { + * .ip = ASPEED_IP_SCU, + * .reg = 0x70, + * .mask = BIT(14), + * .enable = 1, + * .disable = 0 + * }, + * }; + * + * static const struct aspeed_sig_expr sig_expr_LPCRST_LPCRSTS = { + * .signal = "LPCRST", + * .function = "LPCRSTS", + * .ndescs = ARRAY_SIZE(sig_descs_LPCRST_LPCRSTS), + * .descs = &(sig_descs_LPCRST_LPCRSTS)[0], + * }; + * + * static const struct aspeed_sig_expr *sig_exprs_LPCRST_LPCRST[] = { + * &sig_expr_LPCRST_LPCRST, + * &sig_expr_LPCRST_LPCRSTS, + * NULL, + * }; + * ... + * ``` + * + * Both expressions listed in the sig_exprs_LPCRST_LPCRST array need to be set + * to disabled for the associated GPIO to be muxed. + * */ #define ASPEED_IP_SCU 0 -- 2.20.1