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,
{
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;
}
{
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,
{
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,
.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,
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) {
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;
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))
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);