From patchwork Wed Apr 24 22:03:30 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sherman Yin X-Patchwork-Id: 2486571 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork2.kernel.org (Postfix) with ESMTP id DEE38DF25A for ; Wed, 24 Apr 2013 22:04:21 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UV7nQ-0004iT-Rv; Wed, 24 Apr 2013 22:04:13 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UV7nO-000487-C0; Wed, 24 Apr 2013 22:04:10 +0000 Received: from mms3.broadcom.com ([216.31.210.19]) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UV7nL-00047o-K2 for linux-arm-kernel@lists.infradead.org; Wed, 24 Apr 2013 22:04:08 +0000 Received: from [10.9.208.57] by mms3.broadcom.com with ESMTP (Broadcom SMTP Relay (Email Firewall v6.5)); Wed, 24 Apr 2013 14:55:44 -0700 X-Server-Uuid: B86B6450-0931-4310-942E-F00ED04CA7AF Received: from IRVEXCHSMTP3.corp.ad.broadcom.com (10.9.207.53) by IRVEXCHCAS08.corp.ad.broadcom.com (10.9.208.57) with Microsoft SMTP Server (TLS) id 14.1.438.0; Wed, 24 Apr 2013 15:03:55 -0700 Received: from mail-irva-13.broadcom.com (10.10.10.20) by IRVEXCHSMTP3.corp.ad.broadcom.com (10.9.207.53) with Microsoft SMTP Server id 14.1.438.0; Wed, 24 Apr 2013 15:03:55 -0700 Received: from ltrmn-lnxub75-vm (testboard-syin2.ric.broadcom.com [10.136.4.120]) by mail-irva-13.broadcom.com (Postfix) with ESMTP id 2857C39295; Wed, 24 Apr 2013 15:03:55 -0700 (PDT) Received: by ltrmn-lnxub75-vm (Postfix, from userid 35077) id 50D1D60383; Wed, 24 Apr 2013 15:03:50 -0700 (PDT) From: "Sherman Yin" To: linux-arm-kernel@lists.infradead.org Subject: [PATCH] ARM: Adds pin config API to set all configs in one function Date: Wed, 24 Apr 2013 15:03:30 -0700 Message-ID: <1366841010-2823-1-git-send-email-syin@broadcom.com> X-Mailer: git-send-email 1.7.9.5 MIME-Version: 1.0 X-WSS-ID: 7D668B6A2L85639852-01-01 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130424_180407_779853_DA7C40FD X-CRM114-Status: GOOD ( 18.96 ) X-Spam-Score: -4.2 (----) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-4.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/, medium trust [216.31.210.19 listed in list.dnswl.org] -0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: csd@broadcom.com, Sherman Yin , linus.walleij@linaro.org, mmayer@broadcom.com, swarren@wwwdotorg.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Currently, when setting pin configuration in the pinctrl framework, pin_config_set() or pin_config_group_set() is called in a loop to set one configuration at a time for the specified pin or group. pin_config_set_all() and pin_config_group_set_all() are defined to set all configurations for the specified pin or group at the same time. These optional APIs allow pinctrl drivers to optimize and combine pin configurations to reduce the number of register writes required to configure a pin. If both pin_config_set() and pin_config_set_all() are defined by a driver, the latter takes precedence. Similarly for pin_config_group_set_all(). Signed-off-by: Sherman Yin --- drivers/pinctrl/pinconf.c | 74 ++++++++++++++++++++++++++------------- include/linux/pinctrl/pinconf.h | 11 ++++-- 2 files changed, 59 insertions(+), 26 deletions(-) diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index d611ecf..568e4f2 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c @@ -34,7 +34,8 @@ int pinconf_check_ops(struct pinctrl_dev *pctldev) return -EINVAL; } /* We have to be able to config the pins in SOME way */ - if (!ops->pin_config_set && !ops->pin_config_group_set) { + if (!ops->pin_config_set && !ops->pin_config_group_set && + !ops->pin_config_set_all && !ops->pin_config_group_set_all) { dev_err(pctldev->dev, "pinconf has to be able to set a pins config\n"); return -EINVAL; @@ -338,40 +339,65 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting) switch (setting->type) { case PIN_MAP_TYPE_CONFIGS_PIN: - if (!ops->pin_config_set) { - dev_err(pctldev->dev, "missing pin_config_set op\n"); - return -EINVAL; - } - for (i = 0; i < setting->data.configs.num_configs; i++) { - ret = ops->pin_config_set(pctldev, - setting->data.configs.group_or_pin, - setting->data.configs.configs[i]); + if (ops->pin_config_set_all) { + ret = ops->pin_config_set_all(pctldev, + &setting->data.configs); if (ret < 0) { dev_err(pctldev->dev, - "pin_config_set op failed for pin %d config %08lx\n", - setting->data.configs.group_or_pin, - setting->data.configs.configs[i]); + "pin_config_set_all op failed for pin %d\n", + setting->data.configs.group_or_pin); return ret; } - } - break; - case PIN_MAP_TYPE_CONFIGS_GROUP: - if (!ops->pin_config_group_set) { + } else if (ops->pin_config_set) { + for (i = 0; i < setting->data.configs.num_configs; i++) { + ret = ops->pin_config_set(pctldev, + setting->data.configs.group_or_pin, + setting->data.configs.configs[i]); + if (ret < 0) { + dev_err(pctldev->dev, + "pin_config_set op failed for " + "pin %d config %08lx\n", + setting->data.configs.group_or_pin, + setting->data.configs.configs[i]); + return ret; + } + } + } else { dev_err(pctldev->dev, - "missing pin_config_group_set op\n"); + "missing pin_config_set or " + "pin_config_set_all op\n"); return -EINVAL; } - for (i = 0; i < setting->data.configs.num_configs; i++) { - ret = ops->pin_config_group_set(pctldev, - setting->data.configs.group_or_pin, - setting->data.configs.configs[i]); + break; + case PIN_MAP_TYPE_CONFIGS_GROUP: + if (ops->pin_config_group_set_all) { + ret = ops->pin_config_group_set_all(pctldev, + &setting->data.configs); if (ret < 0) { dev_err(pctldev->dev, - "pin_config_group_set op failed for group %d config %08lx\n", - setting->data.configs.group_or_pin, - setting->data.configs.configs[i]); + "pin_config_group_set_all op failed for group %d\n", + setting->data.configs.group_or_pin); return ret; } + } else if (ops->pin_config_group_set) { + for (i = 0; i < setting->data.configs.num_configs; i++) { + ret = ops->pin_config_group_set(pctldev, + setting->data.configs.group_or_pin, + setting->data.configs.configs[i]); + if (ret < 0) { + dev_err(pctldev->dev, + "pin_config_group_set op failed " + "for group %d config %08lx\n", + setting->data.configs.group_or_pin, + setting->data.configs.configs[i]); + return ret; + } + } + } else { + dev_err(pctldev->dev, + "missing pin_config_group_set or " + "pin_config_group_set_all op\n"); + return -EINVAL; } break; default: diff --git a/include/linux/pinctrl/pinconf.h b/include/linux/pinctrl/pinconf.h index e7a7201..b838756 100644 --- a/include/linux/pinctrl/pinconf.h +++ b/include/linux/pinctrl/pinconf.h @@ -16,6 +16,7 @@ struct pinctrl_dev; struct seq_file; +struct pinctrl_setting_configs; /** * struct pinconf_ops - pin config operations, to be implemented by @@ -25,9 +26,11 @@ struct seq_file; * @pin_config_get: get the config of a certain pin, if the requested config * is not available on this controller this should return -ENOTSUPP * and if it is available but disabled it should return -EINVAL - * @pin_config_set: configure an individual pin + * @pin_config_set: apply one configuration to an individual pin + * @pin_config_set_all: apply all configurations to an individual pin * @pin_config_group_get: get configurations for an entire pin group - * @pin_config_group_set: configure all pins in a group + * @pin_config_group_set: apply one configuration to all pins in a group + * @pin_config_group_set_all: apply all configurations to all pins in a group * @pin_config_dbg_show: optional debugfs display hook that will provide * per-device info for a certain pin in debugfs * @pin_config_group_dbg_show: optional debugfs display hook that will provide @@ -45,12 +48,16 @@ struct pinconf_ops { int (*pin_config_set) (struct pinctrl_dev *pctldev, unsigned pin, unsigned long config); + int (*pin_config_set_all) (struct pinctrl_dev *pctldev, + const struct pinctrl_setting_configs *configs); int (*pin_config_group_get) (struct pinctrl_dev *pctldev, unsigned selector, unsigned long *config); int (*pin_config_group_set) (struct pinctrl_dev *pctldev, unsigned selector, unsigned long config); + int (*pin_config_group_set_all) (struct pinctrl_dev *pctldev, + const struct pinctrl_setting_configs *configs); void (*pin_config_dbg_show) (struct pinctrl_dev *pctldev, struct seq_file *s, unsigned offset);