@@ -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);
@@ -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;