diff options
-rw-r--r-- | drivers/pinctrl/sh-pfc/pinctrl.c | 114 | ||||
-rw-r--r-- | 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; |