From patchwork Tue Sep 27 14:50:17 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jeffery X-Patchwork-Id: 675662 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3sk3hw0Kgrz9sRZ for ; Wed, 28 Sep 2016 00:52:32 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=aj.id.au header.i=@aj.id.au header.b=ZM7mNZdZ; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=messagingengine.com header.i=@messagingengine.com header.b=Q5kLQvSi; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934474AbcI0OwS (ORCPT ); Tue, 27 Sep 2016 10:52:18 -0400 Received: from out2-smtp.messagingengine.com ([66.111.4.26]:60688 "EHLO out2-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934427AbcI0OwK (ORCPT ); Tue, 27 Sep 2016 10:52:10 -0400 Received: from compute7.internal (compute7.nyi.internal [10.202.2.47]) by mailout.nyi.internal (Postfix) with ESMTP id 7411820507; Tue, 27 Sep 2016 10:52:03 -0400 (EDT) Received: from frontend1 ([10.202.2.160]) by compute7.internal (MEProxy); Tue, 27 Sep 2016 10:52:03 -0400 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=aj.id.au; h=cc :date:from:in-reply-to:in-reply-to:message-id:references :references:subject:to:x-sasl-enc:x-sasl-enc; s=mesmtp; bh=9kFC3 08FrtkO/0pRSM5iTZp3f48=; b=ZM7mNZdZ8axtWtme80hnMoH117BE4OevzMM+h CtisFrtCMcFpHRKf3tUkyWXjzQthdTqKava7VjMUb6pAxIvAG2jOtzoIG4x+O+a7 R+5ffB6wjNtLJVh1K/SJFbZmNayS4TE4CHyO1gcRiHiN1QO7BFvfkP55e8J1XSHg 5EfnnA= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:in-reply-to:in-reply-to :message-id:references:references:subject:to:x-sasl-enc :x-sasl-enc; s=smtpout; bh=9kFC308FrtkO/0pRSM5iTZp3f48=; b=Q5kLQ vSiIrd1Dab0YSs3njM7seL81WDYDq1srsGZsdDQ6bhiD8tDYch0BsNTVyvA2MBCA hx4mll/IpWg5WyhemMLX3HikZkQOcIlAMbSXfLG0L9Pw1OvngXhsM490cAVGK9ii lOK7t6zVUFlnMFKzuwW2DuXRad+jQYIV2LFpQI= X-Sasl-enc: IGwvNpn16hoYiROGfjCyqb6QlMctM8Isu9sHg8XT2o9t 1474987922 Received: from keelia.au.ibm.com (ppp203-122-213-247.static.internode.on.net [203.122.213.247]) by mail.messagingengine.com (Postfix) with ESMTPA id 3A128F29CD; Tue, 27 Sep 2016 10:51:58 -0400 (EDT) From: Andrew Jeffery To: Linus Walleij Cc: Joel Stanley , Mark Rutland , Rob Herring , linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, openbmc@lists.ozlabs.org, Andrew Jeffery Subject: [PATCH 5/8] pinctrl: aspeed: Enable capture of off-SCU pinmux state Date: Wed, 28 Sep 2016 00:20:17 +0930 Message-Id: X-Mailer: git-send-email 2.7.4 In-Reply-To: References: In-Reply-To: References: Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org The System Control Unit IP in the Aspeed SoCs is typically where the pinmux configuration is found. But not always. On the AST2400 and AST2500 a number of pins depend on state in one of the SIO, LPC or GFX IP blocks, so add support to at least capture what that state is. The pinctrl engine for the Aspeed SoCs doesn't try to inspect or modify the state of the off-SCU IP blocks. Instead, it logs the state requirement with the expectation that the platform designer/maintainer arranges for the appropriate configuration to be applied through the associated drivers. The IP block of interest is encoded in the reg member of struct aspeed_sig_desc. For compatibility with the existing code, the SCU is defined to have an IP value of 0. Signed-off-by: Andrew Jeffery --- drivers/pinctrl/aspeed/pinctrl-aspeed.c | 53 +++++++++++++++++++++++--- drivers/pinctrl/aspeed/pinctrl-aspeed.h | 16 +++++++- 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.c b/drivers/pinctrl/aspeed/pinctrl-aspeed.c index 49aeba912531..21ef195d586f 100644 --- a/drivers/pinctrl/aspeed/pinctrl-aspeed.c +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.c @@ -14,6 +14,8 @@ #include "../core.h" #include "pinctrl-aspeed.h" +const char *const aspeed_pinmux_ips[] = { "SCU", "SIO", "GFX", "LPC" }; + int aspeed_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) { struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev); @@ -78,7 +80,9 @@ int aspeed_pinmux_get_fn_groups(struct pinctrl_dev *pctldev, static inline void aspeed_sig_desc_print_val( const struct aspeed_sig_desc *desc, bool enable, u32 rv) { - pr_debug("SCU%x[0x%08x]=0x%x, got 0x%x from 0x%08x\n", desc->reg, + pr_debug("Want %s%lX[0x%08X]=0x%X, got 0x%X from 0x%08X\n", + aspeed_pinmux_ips[SIG_DESC_IP_FROM_REG(desc->reg)], + SIG_DESC_OFFSET_FROM_REG(desc->reg), desc->mask, enable ? desc->enable : desc->disable, (rv & desc->mask) >> __ffs(desc->mask), rv); } @@ -105,6 +109,8 @@ static bool aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc, unsigned int raw; u32 want; + WARN_ON(SIG_DESC_IP_FROM_REG(desc->reg) != ASPEED_IP_SCU); + if (regmap_read(map, desc->reg, &raw) < 0) return false; @@ -142,9 +148,19 @@ static bool aspeed_sig_expr_eval(const struct aspeed_sig_expr *expr, for (i = 0; i < expr->ndescs; i++) { const struct aspeed_sig_desc *desc = &expr->descs[i]; + size_t ip = SIG_DESC_IP_FROM_REG(desc->reg); + + if (ip == ASPEED_IP_SCU) { + if (!aspeed_sig_desc_eval(desc, enabled, map)) + return false; + } else { + size_t offset = SIG_DESC_OFFSET_FROM_REG(desc->reg); + const char *ip_name = aspeed_pinmux_ips[ip]; + + pr_debug("Ignoring configuration of field %s%X[0x%08X]\n", + ip_name, offset, desc->mask); + } - if (!aspeed_sig_desc_eval(desc, enabled, map)) - return false; } return true; @@ -170,7 +186,14 @@ static bool aspeed_sig_expr_set(const struct aspeed_sig_expr *expr, for (i = 0; i < expr->ndescs; i++) { bool ret; const struct aspeed_sig_desc *desc = &expr->descs[i]; + + size_t offset = SIG_DESC_OFFSET_FROM_REG(desc->reg); + size_t ip = SIG_DESC_IP_FROM_REG(desc->reg); + bool is_scu = (ip == ASPEED_IP_SCU); + const char *ip_name = aspeed_pinmux_ips[ip]; + u32 pattern = enable ? desc->enable : desc->disable; + u32 val = (pattern << __ffs(desc->mask)); /* * Strap registers are configured in hardware or by early-boot @@ -179,11 +202,27 @@ static bool aspeed_sig_expr_set(const struct aspeed_sig_expr *expr, * deconfigured and is the reason we re-evaluate after writing * all descriptor bits. */ - if (desc->reg == HW_STRAP1 || desc->reg == HW_STRAP2) + if (is_scu && (offset == HW_STRAP1 || offset == HW_STRAP2)) continue; - ret = regmap_update_bits(map, desc->reg, desc->mask, - pattern << __ffs(desc->mask)) == 0; + /* + * Sometimes we need help from IP outside the SCU to activate a + * mux request. Report that we need its cooperation. + */ + if (enable && !is_scu) { + pr_debug("Pinmux request for %s requires cooperation of %s IP: Need (%s%X[0x%08X] = 0x%08X\n", + expr->function, ip_name, ip_name, offset, + desc->mask, val); + } + + /* And only read/write SCU registers */ + if (!is_scu) { + pr_debug("Skipping configuration of field %s%X[0x%08X]\n", + ip_name, offset, desc->mask); + continue; + } + + ret = regmap_update_bits(map, desc->reg, desc->mask, val) == 0; if (!ret) return ret; @@ -343,6 +382,8 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function, const struct aspeed_sig_expr **funcs; const struct aspeed_sig_expr ***prios; + pr_debug("Muxing pin %d for %s\n", pin, pfunc->name); + if (!pdesc) return -EINVAL; diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.h b/drivers/pinctrl/aspeed/pinctrl-aspeed.h index 3e72ef8c54bf..4384407d77fb 100644 --- a/drivers/pinctrl/aspeed/pinctrl-aspeed.h +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.h @@ -232,6 +232,15 @@ * group. */ +#define ASPEED_IP_SCU 0 +#define ASPEED_IP_SIO 1 +#define ASPEED_IP_GFX 2 +#define ASPEED_IP_LPC 3 + +#define SIG_DESC_TO_REG(ip, offset) (((ip) << 24) | (offset)) +#define SIG_DESC_IP_FROM_REG(reg) (((reg) >> 24) & GENMASK(7, 0)) +#define SIG_DESC_OFFSET_FROM_REG(reg) ((reg) & GENMASK(11, 0)) + /* * The "Multi-function Pins Mapping and Control" table in the SoC datasheet * references registers by the device/offset mnemonic. The register macros @@ -261,7 +270,10 @@ * A signal descriptor, which describes the register, bits and the * enable/disable values that should be compared or written. * - * @reg: The register offset from base in bytes + * @reg: Split into three fields: + * 31:24: IP selector + * 23:12: Reserved + * 11:0: Register offset * @mask: The mask to apply to the register. The lowest set bit of the mask is * used to derive the shift value. * @enable: The value that enables the function. Value should be in the LSBs, @@ -270,7 +282,7 @@ * LSBs, not at the position of the mask. */ struct aspeed_sig_desc { - unsigned int reg; + u32 reg; u32 mask; u32 enable; u32 disable;