From patchwork Fri Mar 29 02:43:54 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Horman X-Patchwork-Id: 2363111 Return-Path: X-Original-To: patchwork-ltsi-dev@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) by patchwork1.kernel.org (Postfix) with ESMTP id 15F0C3FD40 for ; Fri, 29 Mar 2013 02:56:50 +0000 (UTC) Received: from mail.linux-foundation.org (localhost [IPv6:::1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 1EE8DB5D; Fri, 29 Mar 2013 02:47:45 +0000 (UTC) X-Original-To: ltsi-dev@lists.linuxfoundation.org Delivered-To: ltsi-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTP id 67E65B11 for ; Fri, 29 Mar 2013 02:47:40 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from kirsty.vergenet.net (kirsty.vergenet.net [202.4.237.240]) by smtp1.linuxfoundation.org (Postfix) with ESMTP id 4A78020181 for ; Fri, 29 Mar 2013 02:47:37 +0000 (UTC) Received: from ayumi.akashicho.tokyo.vergenet.net (p8120-ipbfp1001kobeminato.hyogo.ocn.ne.jp [118.10.137.120]) by kirsty.vergenet.net (Postfix) with ESMTP id 32F322C6A7A; Fri, 29 Mar 2013 13:45:59 +1100 (EST) Received: by ayumi.akashicho.tokyo.vergenet.net (Postfix, from userid 7100) id CD2BBEDEA2D; Fri, 29 Mar 2013 11:45:57 +0900 (JST) From: Simon Horman To: ltsi-dev@lists.linuxfoundation.org Date: Fri, 29 Mar 2013 11:43:54 +0900 Message-Id: <1364525119-31791-306-git-send-email-horms+renesas@verge.net.au> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1364525119-31791-1-git-send-email-horms+renesas@verge.net.au> References: <1364525119-31791-1-git-send-email-horms+renesas@verge.net.au> X-Spam-Status: No, score=-3.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, RP_MATCHES_RCVD autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Magnus Damm Subject: [LTSI-dev] [PATCH/RFC 305/390] sh-pfc: Expose real groups and functions in pinctrl/pinmux operations X-BeenThere: ltsi-dev@lists.linuxfoundation.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: "A list to discuss patches, development, and other things related to the LTSI project" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ltsi-dev-bounces@lists.linuxfoundation.org Errors-To: ltsi-dev-bounces@lists.linuxfoundation.org From: Laurent Pinchart The sh-pfc driver exposes one fake group and function per GPIO pin. As the pinctrl and pinmux APIs are not used by any SuperH and SH Mobile board or driver, drop the fake groups and functions and replace them by a real pinctrl and pinmux implementation. Groups and functions must now be explicitly provided by PFC SoC-specific data. Signed-off-by: Laurent Pinchart Acked-by: Linus Walleij (cherry picked from commit 3d8d9f1df93362f319cf60b9ad10721a059b058f) Signed-off-by: Simon Horman --- drivers/pinctrl/sh-pfc/pinctrl.c | 114 +++++++++++++++++++------------------- drivers/pinctrl/sh-pfc/sh_pfc.h | 35 ++++++++++++ 2 files changed, 93 insertions(+), 56 deletions(-) diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c index c9e9a1d..c7f3c40 100644 --- a/drivers/pinctrl/sh-pfc/pinctrl.c +++ b/drivers/pinctrl/sh-pfc/pinctrl.c @@ -31,18 +31,14 @@ struct sh_pfc_pinctrl { struct sh_pfc *pfc; - struct pinmux_func **functions; - unsigned int nr_functions; - - struct pinctrl_pin_desc *pads; - unsigned int nr_pads; + struct pinctrl_pin_desc *pins; }; static int sh_pfc_get_groups_count(struct pinctrl_dev *pctldev) { struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); - return pmx->nr_pads; + return pmx->pfc->info->nr_groups; } static const char *sh_pfc_get_group_name(struct pinctrl_dev *pctldev, @@ -50,16 +46,16 @@ static const char *sh_pfc_get_group_name(struct pinctrl_dev *pctldev, { struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); - return pmx->pads[selector].name; + return pmx->pfc->info->groups[selector].name; } -static int sh_pfc_get_group_pins(struct pinctrl_dev *pctldev, unsigned group, +static int sh_pfc_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, const unsigned **pins, unsigned *num_pins) { struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); - *pins = &pmx->pads[group].number; - *num_pins = 1; + *pins = pmx->pfc->info->groups[selector].pins; + *num_pins = pmx->pfc->info->groups[selector].nr_pins; return 0; } @@ -81,7 +77,7 @@ static int sh_pfc_get_functions_count(struct pinctrl_dev *pctldev) { struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); - return pmx->nr_functions; + return pmx->pfc->info->nr_functions; } static const char *sh_pfc_get_function_name(struct pinctrl_dev *pctldev, @@ -89,30 +85,67 @@ static const char *sh_pfc_get_function_name(struct pinctrl_dev *pctldev, { struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); - return pmx->functions[selector]->name; + return pmx->pfc->info->functions[selector].name; } -static int sh_pfc_get_function_groups(struct pinctrl_dev *pctldev, unsigned func, +static int sh_pfc_get_function_groups(struct pinctrl_dev *pctldev, + unsigned selector, const char * const **groups, unsigned * const num_groups) { struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); - *groups = &pmx->functions[func]->name; - *num_groups = 1; + *groups = pmx->pfc->info->functions[selector].groups; + *num_groups = pmx->pfc->info->functions[selector].nr_groups; return 0; } -static int sh_pfc_noop_enable(struct pinctrl_dev *pctldev, unsigned func, +static int sh_pfc_func_enable(struct pinctrl_dev *pctldev, unsigned selector, unsigned group) { - return 0; + struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); + struct sh_pfc *pfc = pmx->pfc; + const struct sh_pfc_pin_group *grp = &pfc->info->groups[group]; + unsigned long flags; + unsigned int i; + int ret = -EINVAL; + + spin_lock_irqsave(&pfc->lock, flags); + + for (i = 0; i < grp->nr_pins; ++i) { + if (sh_pfc_config_mux(pfc, grp->mux[i], PINMUX_TYPE_FUNCTION, + GPIO_CFG_DRYRUN)) + goto done; + + if (sh_pfc_config_mux(pfc, grp->mux[i], PINMUX_TYPE_FUNCTION, + GPIO_CFG_REQ)) + goto done; + } + + ret = 0; + +done: + spin_unlock_irqrestore(&pfc->lock, flags); + return ret; } -static void sh_pfc_noop_disable(struct pinctrl_dev *pctldev, unsigned func, +static void sh_pfc_func_disable(struct pinctrl_dev *pctldev, unsigned selector, unsigned group) { + struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev); + struct sh_pfc *pfc = pmx->pfc; + const struct sh_pfc_pin_group *grp = &pfc->info->groups[group]; + unsigned long flags; + unsigned int i; + + spin_lock_irqsave(&pfc->lock, flags); + + for (i = 0; i < grp->nr_pins; ++i) + sh_pfc_config_mux(pfc, grp->mux[i], PINMUX_TYPE_FUNCTION, + GPIO_CFG_FREE); + + spin_unlock_irqrestore(&pfc->lock, flags); } static int sh_pfc_reconfig_pin(struct sh_pfc *pfc, unsigned offset, @@ -234,8 +267,8 @@ static const struct pinmux_ops sh_pfc_pinmux_ops = { .get_functions_count = sh_pfc_get_functions_count, .get_function_name = sh_pfc_get_function_name, .get_function_groups = sh_pfc_get_function_groups, - .enable = sh_pfc_noop_enable, - .disable = sh_pfc_noop_disable, + .enable = sh_pfc_func_enable, + .disable = sh_pfc_func_disable, .gpio_request_enable = sh_pfc_gpio_request_enable, .gpio_disable_free = sh_pfc_gpio_disable_free, .gpio_set_direction = sh_pfc_gpio_set_direction, @@ -312,10 +345,10 @@ static int sh_pfc_map_pins(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) nr_ranges = pfc->info->nr_ranges; } - pmx->pads = devm_kzalloc(pfc->dev, - sizeof(*pmx->pads) * pfc->info->nr_pins, + pmx->pins = devm_kzalloc(pfc->dev, + sizeof(*pmx->pins) * pfc->info->nr_pins, GFP_KERNEL); - if (unlikely(!pmx->pads)) + if (unlikely(!pmx->pins)) return -ENOMEM; for (i = 0, nr_pins = 0; i < nr_ranges; ++i) { @@ -324,7 +357,7 @@ static int sh_pfc_map_pins(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) for (number = range->begin; number <= range->end; number++, nr_pins++) { - struct pinctrl_pin_desc *pin = &pmx->pads[nr_pins]; + struct pinctrl_pin_desc *pin = &pmx->pins[nr_pins]; struct sh_pfc_pin *info = &pfc->info->pins[nr_pins]; pin->number = number; @@ -337,37 +370,10 @@ static int sh_pfc_map_pins(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) return nr_ranges; } -static int sh_pfc_map_functions(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx) -{ - int i, fn; - - for (i = 0; i < pfc->info->nr_func_gpios; i++) { - struct pinmux_func *func = pfc->info->func_gpios + i; - - if (func->enum_id) - pmx->nr_functions++; - } - - pmx->functions = devm_kzalloc(pfc->dev, pmx->nr_functions * - sizeof(*pmx->functions), GFP_KERNEL); - if (unlikely(!pmx->functions)) - return -ENOMEM; - - for (i = fn = 0; i < pfc->info->nr_func_gpios; i++) { - struct pinmux_func *func = pfc->info->func_gpios + i; - - if (func->enum_id) - pmx->functions[fn++] = func; - } - - return 0; -} - int sh_pfc_register_pinctrl(struct sh_pfc *pfc) { struct sh_pfc_pinctrl *pmx; int nr_ranges; - int ret; pmx = devm_kzalloc(pfc->dev, sizeof(*pmx), GFP_KERNEL); if (unlikely(!pmx)) @@ -380,16 +386,12 @@ int sh_pfc_register_pinctrl(struct sh_pfc *pfc) if (unlikely(nr_ranges < 0)) return nr_ranges; - ret = sh_pfc_map_functions(pfc, pmx); - if (unlikely(ret != 0)) - return ret; - pmx->pctl_desc.name = DRV_NAME; pmx->pctl_desc.owner = THIS_MODULE; pmx->pctl_desc.pctlops = &sh_pfc_pinctrl_ops; pmx->pctl_desc.pmxops = &sh_pfc_pinmux_ops; pmx->pctl_desc.confops = &sh_pfc_pinconf_ops; - pmx->pctl_desc.pins = pmx->pads; + pmx->pctl_desc.pins = pmx->pins; pmx->pctl_desc.npins = pfc->info->nr_pins; pmx->pctl = pinctrl_register(&pmx->pctl_desc, pfc->dev, pmx); diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h index dbcaa60..028e29a 100644 --- a/drivers/pinctrl/sh-pfc/sh_pfc.h +++ b/drivers/pinctrl/sh-pfc/sh_pfc.h @@ -16,6 +16,8 @@ typedef unsigned short pinmux_enum_t; +#define SH_PFC_MARK_INVALID ((pinmux_enum_t)-1) + enum { PINMUX_TYPE_NONE, @@ -40,6 +42,34 @@ struct sh_pfc_pin { const char *name; }; +#define SH_PFC_PIN_GROUP(n) \ + { \ + .name = #n, \ + .pins = n##_pins, \ + .mux = n##_mux, \ + .nr_pins = ARRAY_SIZE(n##_pins), \ + } + +struct sh_pfc_pin_group { + const char *name; + const unsigned int *pins; + const unsigned int *mux; + unsigned int nr_pins; +}; + +#define SH_PFC_FUNCTION(n) \ + { \ + .name = #n, \ + .groups = n##_groups, \ + .nr_groups = ARRAY_SIZE(n##_groups), \ + } + +struct sh_pfc_function { + const char *name; + const char * const *groups; + unsigned int nr_groups; +}; + struct pinmux_func { const pinmux_enum_t enum_id; const char *name; @@ -113,6 +143,11 @@ struct sh_pfc_soc_info { unsigned int nr_pins; const struct pinmux_range *ranges; unsigned int nr_ranges; + const struct sh_pfc_pin_group *groups; + unsigned int nr_groups; + const struct sh_pfc_function *functions; + unsigned int nr_functions; + struct pinmux_func *func_gpios; unsigned int nr_func_gpios;