summaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/freescale/pinctrl-imx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/freescale/pinctrl-imx.c')
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx.c300
1 files changed, 147 insertions, 153 deletions
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c
index 5ef7e875b50e..a7ace9e1ad81 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx.c
@@ -27,6 +27,7 @@
#include <linux/regmap.h>
#include "../core.h"
+#include "../pinmux.h"
#include "pinctrl-imx.h"
/* The bits in CONFIG cell defined in binding doc*/
@@ -42,59 +43,25 @@ struct imx_pinctrl {
struct pinctrl_dev *pctl;
void __iomem *base;
void __iomem *input_sel_base;
- const struct imx_pinctrl_soc_info *info;
+ struct imx_pinctrl_soc_info *info;
};
-static inline const struct imx_pin_group *imx_pinctrl_find_group_by_name(
- const struct imx_pinctrl_soc_info *info,
+static inline const struct group_desc *imx_pinctrl_find_group_by_name(
+ struct pinctrl_dev *pctldev,
const char *name)
{
- const struct imx_pin_group *grp = NULL;
+ const struct group_desc *grp = NULL;
int i;
- for (i = 0; i < info->ngroups; i++) {
- if (!strcmp(info->groups[i].name, name)) {
- grp = &info->groups[i];
+ for (i = 0; i < pctldev->num_groups; i++) {
+ grp = pinctrl_generic_get_group(pctldev, i);
+ if (grp && !strcmp(grp->name, name))
break;
- }
}
return grp;
}
-static int imx_get_groups_count(struct pinctrl_dev *pctldev)
-{
- struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct imx_pinctrl_soc_info *info = ipctl->info;
-
- return info->ngroups;
-}
-
-static const char *imx_get_group_name(struct pinctrl_dev *pctldev,
- unsigned selector)
-{
- struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct imx_pinctrl_soc_info *info = ipctl->info;
-
- return info->groups[selector].name;
-}
-
-static int imx_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
- const unsigned **pins,
- unsigned *npins)
-{
- struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct imx_pinctrl_soc_info *info = ipctl->info;
-
- if (selector >= info->ngroups)
- return -EINVAL;
-
- *pins = info->groups[selector].pin_ids;
- *npins = info->groups[selector].npins;
-
- return 0;
-}
-
static void imx_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned offset)
{
@@ -106,8 +73,8 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev,
struct pinctrl_map **map, unsigned *num_maps)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct imx_pinctrl_soc_info *info = ipctl->info;
- const struct imx_pin_group *grp;
+ struct imx_pinctrl_soc_info *info = ipctl->info;
+ const struct group_desc *grp;
struct pinctrl_map *new_map;
struct device_node *parent;
int map_num = 1;
@@ -117,15 +84,17 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev,
* first find the group of this node and check if we need create
* config maps for pins
*/
- grp = imx_pinctrl_find_group_by_name(info, np->name);
+ grp = imx_pinctrl_find_group_by_name(pctldev, np->name);
if (!grp) {
dev_err(info->dev, "unable to find group for node %s\n",
np->name);
return -EINVAL;
}
- for (i = 0; i < grp->npins; i++) {
- if (!(grp->pins[i].config & IMX_NO_PAD_CTL))
+ for (i = 0; i < grp->num_pins; i++) {
+ struct imx_pin *pin = &((struct imx_pin *)(grp->data))[i];
+
+ if (!(pin->config & IMX_NO_PAD_CTL))
map_num++;
}
@@ -149,12 +118,14 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev,
/* create config map */
new_map++;
- for (i = j = 0; i < grp->npins; i++) {
- if (!(grp->pins[i].config & IMX_NO_PAD_CTL)) {
+ for (i = j = 0; i < grp->num_pins; i++) {
+ struct imx_pin *pin = &((struct imx_pin *)(grp->data))[i];
+
+ if (!(pin->config & IMX_NO_PAD_CTL)) {
new_map[j].type = PIN_MAP_TYPE_CONFIGS_PIN;
new_map[j].data.configs.group_or_pin =
- pin_get_name(pctldev, grp->pins[i].pin);
- new_map[j].data.configs.configs = &grp->pins[i].config;
+ pin_get_name(pctldev, pin->pin);
+ new_map[j].data.configs.configs = &pin->config;
new_map[j].data.configs.num_configs = 1;
j++;
}
@@ -173,9 +144,9 @@ static void imx_dt_free_map(struct pinctrl_dev *pctldev,
}
static const struct pinctrl_ops imx_pctrl_ops = {
- .get_groups_count = imx_get_groups_count,
- .get_group_name = imx_get_group_name,
- .get_group_pins = imx_get_group_pins,
+ .get_groups_count = pinctrl_generic_get_group_count,
+ .get_group_name = pinctrl_generic_get_group_name,
+ .get_group_pins = pinctrl_generic_get_group_pins,
.pin_dbg_show = imx_pin_dbg_show,
.dt_node_to_map = imx_dt_node_to_map,
.dt_free_map = imx_dt_free_map,
@@ -186,24 +157,33 @@ static int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
unsigned group)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct imx_pinctrl_soc_info *info = ipctl->info;
+ struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg;
unsigned int npins, pin_id;
int i;
- struct imx_pin_group *grp;
+ struct group_desc *grp = NULL;
+ struct function_desc *func = NULL;
/*
* Configure the mux mode for each pin in the group for a specific
* function.
*/
- grp = &info->groups[group];
- npins = grp->npins;
+ grp = pinctrl_generic_get_group(pctldev, group);
+ if (!grp)
+ return -EINVAL;
+
+ func = pinmux_generic_get_function(pctldev, selector);
+ if (!func)
+ return -EINVAL;
+
+ npins = grp->num_pins;
dev_dbg(ipctl->dev, "enable function %s group %s\n",
- info->functions[selector].name, grp->name);
+ func->name, grp->name);
for (i = 0; i < npins; i++) {
- struct imx_pin *pin = &grp->pins[i];
+ struct imx_pin *pin = &((struct imx_pin *)(grp->data))[i];
+
pin_id = pin->pin;
pin_reg = &info->pin_regs[pin_id];
@@ -272,43 +252,13 @@ static int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
return 0;
}
-static int imx_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
-{
- struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct imx_pinctrl_soc_info *info = ipctl->info;
-
- return info->nfunctions;
-}
-
-static const char *imx_pmx_get_func_name(struct pinctrl_dev *pctldev,
- unsigned selector)
-{
- struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct imx_pinctrl_soc_info *info = ipctl->info;
-
- return info->functions[selector].name;
-}
-
-static int imx_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
- const char * const **groups,
- unsigned * const num_groups)
-{
- struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct imx_pinctrl_soc_info *info = ipctl->info;
-
- *groups = info->functions[selector].groups;
- *num_groups = info->functions[selector].num_groups;
-
- return 0;
-}
-
static int imx_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range, unsigned offset)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct imx_pinctrl_soc_info *info = ipctl->info;
+ struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg;
- struct imx_pin_group *grp;
+ struct group_desc *grp;
struct imx_pin *imx_pin;
unsigned int pin, group;
u32 reg;
@@ -322,10 +272,12 @@ static int imx_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
return -EINVAL;
/* Find the pinctrl config with GPIO mux mode for the requested pin */
- for (group = 0; group < info->ngroups; group++) {
- grp = &info->groups[group];
- for (pin = 0; pin < grp->npins; pin++) {
- imx_pin = &grp->pins[pin];
+ for (group = 0; group < pctldev->num_groups; group++) {
+ grp = pinctrl_generic_get_group(pctldev, group);
+ if (!grp)
+ continue;
+ for (pin = 0; pin < grp->num_pins; pin++) {
+ imx_pin = &((struct imx_pin *)(grp->data))[pin];
if (imx_pin->pin == offset && !imx_pin->mux_mode)
goto mux_pin;
}
@@ -346,7 +298,7 @@ static void imx_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range, unsigned offset)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct imx_pinctrl_soc_info *info = ipctl->info;
+ struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg;
u32 reg;
@@ -371,7 +323,7 @@ static int imx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range, unsigned offset, bool input)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct imx_pinctrl_soc_info *info = ipctl->info;
+ struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg;
u32 reg;
@@ -398,9 +350,9 @@ static int imx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
}
static const struct pinmux_ops imx_pmx_ops = {
- .get_functions_count = imx_pmx_get_funcs_count,
- .get_function_name = imx_pmx_get_func_name,
- .get_function_groups = imx_pmx_get_groups,
+ .get_functions_count = pinmux_generic_get_function_count,
+ .get_function_name = pinmux_generic_get_function_name,
+ .get_function_groups = pinmux_generic_get_function_groups,
.set_mux = imx_pmx_set,
.gpio_request_enable = imx_pmx_gpio_request_enable,
.gpio_disable_free = imx_pmx_gpio_disable_free,
@@ -411,7 +363,7 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev,
unsigned pin_id, unsigned long *config)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct imx_pinctrl_soc_info *info = ipctl->info;
+ struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
if (pin_reg->conf_reg == -1) {
@@ -433,7 +385,7 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev,
unsigned num_configs)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct imx_pinctrl_soc_info *info = ipctl->info;
+ struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
int i;
@@ -467,7 +419,7 @@ static void imx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned pin_id)
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct imx_pinctrl_soc_info *info = ipctl->info;
+ struct imx_pinctrl_soc_info *info = ipctl->info;
const struct imx_pin_reg *pin_reg = &info->pin_regs[pin_id];
unsigned long config;
@@ -483,20 +435,22 @@ static void imx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
static void imx_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned group)
{
- struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct imx_pinctrl_soc_info *info = ipctl->info;
- struct imx_pin_group *grp;
+ struct group_desc *grp;
unsigned long config;
const char *name;
int i, ret;
- if (group > info->ngroups)
+ if (group > pctldev->num_groups)
return;
seq_printf(s, "\n");
- grp = &info->groups[group];
- for (i = 0; i < grp->npins; i++) {
- struct imx_pin *pin = &grp->pins[i];
+ grp = pinctrl_generic_get_group(pctldev, group);
+ if (!grp)
+ return;
+
+ for (i = 0; i < grp->num_pins; i++) {
+ struct imx_pin *pin = &((struct imx_pin *)(grp->data))[i];
+
name = pin_get_name(pctldev, pin->pin);
ret = imx_pinconf_get(pctldev, pin->pin, &config);
if (ret)
@@ -520,7 +474,7 @@ static const struct pinconf_ops imx_pinconf_ops = {
#define SHARE_FSL_PIN_SIZE 20
static int imx_pinctrl_parse_groups(struct device_node *np,
- struct imx_pin_group *grp,
+ struct group_desc *grp,
struct imx_pinctrl_soc_info *info,
u32 index)
{
@@ -554,20 +508,20 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
return -EINVAL;
}
- grp->npins = size / pin_size;
- grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(struct imx_pin),
- GFP_KERNEL);
- grp->pin_ids = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
- GFP_KERNEL);
- if (!grp->pins || ! grp->pin_ids)
+ grp->num_pins = size / pin_size;
+ grp->data = devm_kzalloc(info->dev, grp->num_pins *
+ sizeof(struct imx_pin), GFP_KERNEL);
+ grp->pins = devm_kzalloc(info->dev, grp->num_pins *
+ sizeof(unsigned int), GFP_KERNEL);
+ if (!grp->pins || !grp->data)
return -ENOMEM;
- for (i = 0; i < grp->npins; i++) {
+ for (i = 0; i < grp->num_pins; i++) {
u32 mux_reg = be32_to_cpu(*list++);
u32 conf_reg;
unsigned int pin_id;
struct imx_pin_reg *pin_reg;
- struct imx_pin *pin = &grp->pins[i];
+ struct imx_pin *pin = &((struct imx_pin *)(grp->data))[i];
if (!(info->flags & ZERO_OFFSET_VALID) && !mux_reg)
mux_reg = -1;
@@ -583,7 +537,7 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
pin_id = (mux_reg != -1) ? mux_reg / 4 : conf_reg / 4;
pin_reg = &info->pin_regs[pin_id];
pin->pin = pin_id;
- grp->pin_ids[i] = pin_id;
+ grp->pins[i] = pin_id;
pin_reg->mux_reg = mux_reg;
pin_reg->conf_reg = conf_reg;
pin->input_reg = be32_to_cpu(*list++);
@@ -604,31 +558,46 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
}
static int imx_pinctrl_parse_functions(struct device_node *np,
- struct imx_pinctrl_soc_info *info,
+ struct imx_pinctrl *ipctl,
u32 index)
{
+ struct pinctrl_dev *pctl = ipctl->pctl;
+ struct imx_pinctrl_soc_info *info = ipctl->info;
struct device_node *child;
- struct imx_pmx_func *func;
- struct imx_pin_group *grp;
+ struct function_desc *func;
+ struct group_desc *grp;
u32 i = 0;
dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
- func = &info->functions[index];
+ func = pinmux_generic_get_function(pctl, index);
+ if (!func)
+ return -EINVAL;
/* Initialise function */
func->name = np->name;
- func->num_groups = of_get_child_count(np);
- if (func->num_groups == 0) {
+ func->num_group_names = of_get_child_count(np);
+ if (func->num_group_names == 0) {
dev_err(info->dev, "no groups defined in %s\n", np->full_name);
return -EINVAL;
}
- func->groups = devm_kzalloc(info->dev,
- func->num_groups * sizeof(char *), GFP_KERNEL);
+ func->group_names = devm_kzalloc(info->dev,
+ func->num_group_names *
+ sizeof(char *), GFP_KERNEL);
for_each_child_of_node(np, child) {
- func->groups[i] = child->name;
- grp = &info->groups[info->group_index++];
+ func->group_names[i] = child->name;
+
+ grp = devm_kzalloc(info->dev, sizeof(struct group_desc),
+ GFP_KERNEL);
+ if (!grp)
+ return -ENOMEM;
+
+ mutex_lock(&info->mutex);
+ radix_tree_insert(&pctl->pin_group_tree,
+ info->group_index++, grp);
+ mutex_unlock(&info->mutex);
+
imx_pinctrl_parse_groups(child, grp, info, i++);
}
@@ -659,10 +628,12 @@ static bool imx_pinctrl_dt_is_flat_functions(struct device_node *np)
}
static int imx_pinctrl_probe_dt(struct platform_device *pdev,
- struct imx_pinctrl_soc_info *info)
+ struct imx_pinctrl *ipctl)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *child;
+ struct pinctrl_dev *pctl = ipctl->pctl;
+ struct imx_pinctrl_soc_info *info = ipctl->info;
u32 nfuncs = 0;
u32 i = 0;
bool flat_funcs;
@@ -681,35 +652,50 @@ static int imx_pinctrl_probe_dt(struct platform_device *pdev,
}
}
- info->nfunctions = nfuncs;
- info->functions = devm_kzalloc(&pdev->dev, nfuncs * sizeof(struct imx_pmx_func),
+ for (i = 0; i < nfuncs; i++) {
+ struct function_desc *function;
+
+ function = devm_kzalloc(&pdev->dev, sizeof(*function),
GFP_KERNEL);
- if (!info->functions)
- return -ENOMEM;
+ if (!function)
+ return -ENOMEM;
+
+ mutex_lock(&info->mutex);
+ radix_tree_insert(&pctl->pin_function_tree, i, function);
+ mutex_unlock(&info->mutex);
+ }
+ pctl->num_functions = nfuncs;
info->group_index = 0;
if (flat_funcs) {
- info->ngroups = of_get_child_count(np);
+ pctl->num_groups = of_get_child_count(np);
} else {
- info->ngroups = 0;
+ pctl->num_groups = 0;
for_each_child_of_node(np, child)
- info->ngroups += of_get_child_count(child);
+ pctl->num_groups += of_get_child_count(child);
}
- info->groups = devm_kzalloc(&pdev->dev, info->ngroups * sizeof(struct imx_pin_group),
- GFP_KERNEL);
- if (!info->groups)
- return -ENOMEM;
if (flat_funcs) {
- imx_pinctrl_parse_functions(np, info, 0);
+ imx_pinctrl_parse_functions(np, ipctl, 0);
} else {
+ i = 0;
for_each_child_of_node(np, child)
- imx_pinctrl_parse_functions(child, info, i++);
+ imx_pinctrl_parse_functions(child, ipctl, i++);
}
return 0;
}
+/*
+ * imx_free_resources() - free memory used by this driver
+ * @info: info driver instance
+ */
+static void imx_free_resources(struct imx_pinctrl *ipctl)
+{
+ if (ipctl->pctl)
+ pinctrl_unregister(ipctl->pctl);
+}
+
int imx_pinctrl_probe(struct platform_device *pdev,
struct imx_pinctrl_soc_info *info)
{
@@ -783,23 +769,31 @@ int imx_pinctrl_probe(struct platform_device *pdev,
imx_pinctrl_desc->confops = &imx_pinconf_ops;
imx_pinctrl_desc->owner = THIS_MODULE;
- ret = imx_pinctrl_probe_dt(pdev, info);
- if (ret) {
- dev_err(&pdev->dev, "fail to probe dt properties\n");
- return ret;
- }
+ mutex_init(&info->mutex);
ipctl->info = info;
ipctl->dev = info->dev;
platform_set_drvdata(pdev, ipctl);
- ipctl->pctl = devm_pinctrl_register(&pdev->dev,
- imx_pinctrl_desc, ipctl);
- if (IS_ERR(ipctl->pctl)) {
+ ret = devm_pinctrl_register_and_init(&pdev->dev,
+ imx_pinctrl_desc, ipctl,
+ &ipctl->pctl);
+ if (ret) {
dev_err(&pdev->dev, "could not register IMX pinctrl driver\n");
- return PTR_ERR(ipctl->pctl);
+ goto free;
+ }
+
+ ret = imx_pinctrl_probe_dt(pdev, ipctl);
+ if (ret) {
+ dev_err(&pdev->dev, "fail to probe dt properties\n");
+ goto free;
}
dev_info(&pdev->dev, "initialized IMX pinctrl driver\n");
return 0;
+
+free:
+ imx_free_resources(ipctl);
+
+ return ret;
}