summaryrefslogtreecommitdiff
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.c262
1 files changed, 98 insertions, 164 deletions
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c
index 188001beb298..731c58ad43ee 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx.c
@@ -11,15 +11,18 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/mfd/syscon.h>
+#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
-#include <linux/slab.h>
-#include <linux/regmap.h>
#include "../core.h"
#include "../pinconf.h"
@@ -34,16 +37,16 @@ static inline const struct group_desc *imx_pinctrl_find_group_by_name(
struct pinctrl_dev *pctldev,
const char *name)
{
- const struct group_desc *grp = NULL;
+ const struct group_desc *grp;
int i;
for (i = 0; i < pctldev->num_groups; i++) {
grp = pinctrl_generic_get_group(pctldev, i);
- if (grp && !strcmp(grp->name, name))
- break;
+ if (grp && !strcmp(grp->grp.name, name))
+ return grp;
}
- return grp;
+ return NULL;
}
static void imx_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
@@ -76,9 +79,9 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev,
}
if (info->flags & IMX_USE_SCU) {
- map_num += grp->num_pins;
+ map_num += grp->grp.npins;
} else {
- for (i = 0; i < grp->num_pins; i++) {
+ for (i = 0; i < grp->grp.npins; i++) {
pin = &((struct imx_pin *)(grp->data))[i];
if (!(pin->conf.mmio.config & IMX_NO_PAD_CTL))
map_num++;
@@ -106,7 +109,7 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev,
/* create config map */
new_map++;
- for (i = j = 0; i < grp->num_pins; i++) {
+ for (i = j = 0; i < grp->grp.npins; i++) {
pin = &((struct imx_pin *)(grp->data))[i];
/*
@@ -242,7 +245,7 @@ static int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
{
struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct imx_pinctrl_soc_info *info = ipctl->info;
- struct function_desc *func;
+ const struct function_desc *func;
struct group_desc *grp;
struct imx_pin *pin;
unsigned int npins;
@@ -260,10 +263,10 @@ static int imx_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
if (!func)
return -EINVAL;
- npins = grp->num_pins;
+ npins = grp->grp.npins;
dev_dbg(ipctl->dev, "enable function %s group %s\n",
- func->name, grp->name);
+ func->func->name, grp->grp.name);
for (i = 0; i < npins; i++) {
/*
@@ -289,62 +292,6 @@ struct pinmux_ops imx_pmx_ops = {
.set_mux = imx_pmx_set,
};
-/* decode generic config into raw register values */
-static u32 imx_pinconf_decode_generic_config(struct imx_pinctrl *ipctl,
- unsigned long *configs,
- unsigned int num_configs)
-{
- const struct imx_pinctrl_soc_info *info = ipctl->info;
- const struct imx_cfg_params_decode *decode;
- enum pin_config_param param;
- u32 raw_config = 0;
- u32 param_val;
- int i, j;
-
- WARN_ON(num_configs > info->num_decodes);
-
- for (i = 0; i < num_configs; i++) {
- param = pinconf_to_config_param(configs[i]);
- param_val = pinconf_to_config_argument(configs[i]);
- decode = info->decodes;
- for (j = 0; j < info->num_decodes; j++) {
- if (param == decode->param) {
- if (decode->invert)
- param_val = !param_val;
- raw_config |= (param_val << decode->shift)
- & decode->mask;
- break;
- }
- decode++;
- }
- }
-
- if (info->fixup)
- info->fixup(configs, num_configs, &raw_config);
-
- return raw_config;
-}
-
-static u32 imx_pinconf_parse_generic_config(struct device_node *np,
- struct imx_pinctrl *ipctl)
-{
- const struct imx_pinctrl_soc_info *info = ipctl->info;
- struct pinctrl_dev *pctl = ipctl->pctl;
- unsigned int num_configs;
- unsigned long *configs;
- int ret;
-
- if (!info->generic_pinconf)
- return 0;
-
- ret = pinconf_generic_parse_dt_config(np, pctl, &configs,
- &num_configs);
- if (ret)
- return 0;
-
- return imx_pinconf_decode_generic_config(ipctl, configs, num_configs);
-}
-
static int imx_pinconf_get_mmio(struct pinctrl_dev *pctldev, unsigned pin_id,
unsigned long *config)
{
@@ -373,7 +320,7 @@ static int imx_pinconf_get(struct pinctrl_dev *pctldev,
const struct imx_pinctrl_soc_info *info = ipctl->info;
if (info->flags & IMX_USE_SCU)
- return imx_pinconf_get_scu(pctldev, pin_id, config);
+ return info->imx_pinconf_get(pctldev, pin_id, config);
else
return imx_pinconf_get_mmio(pctldev, pin_id, config);
}
@@ -423,7 +370,7 @@ static int imx_pinconf_set(struct pinctrl_dev *pctldev,
const struct imx_pinctrl_soc_info *info = ipctl->info;
if (info->flags & IMX_USE_SCU)
- return imx_pinconf_set_scu(pctldev, pin_id,
+ return info->imx_pinconf_set(pctldev, pin_id,
configs, num_configs);
else
return imx_pinconf_set_mmio(pctldev, pin_id,
@@ -440,7 +387,7 @@ static void imx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
int ret;
if (info->flags & IMX_USE_SCU) {
- ret = imx_pinconf_get_scu(pctldev, pin_id, &config);
+ ret = info->imx_pinconf_get(pctldev, pin_id, &config);
if (ret) {
dev_err(ipctl->dev, "failed to get %s pinconf\n",
pin_get_name(pctldev, pin_id));
@@ -449,7 +396,7 @@ static void imx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
}
} else {
pin_reg = &ipctl->pin_regs[pin_id];
- if (!pin_reg || pin_reg->conf_reg == -1) {
+ if (pin_reg->conf_reg == -1) {
seq_puts(s, "N/A");
return;
}
@@ -476,7 +423,7 @@ static void imx_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
if (!grp)
return;
- for (i = 0; i < grp->num_pins; i++) {
+ for (i = 0; i < grp->grp.npins; i++) {
struct imx_pin *pin = &((struct imx_pin *)(grp->data))[i];
name = pin_get_name(pctldev, pin->pin);
@@ -497,7 +444,6 @@ static const struct pinconf_ops imx_pinconf_ops = {
/*
* Each pin represented in fsl,pins consists of a number of u32 PIN_FUNC_ID
* and 1 u32 CONFIG, the total size is PIN_FUNC_ID + CONFIG for each pin.
- * For generic_pinconf case, there's no extra u32 CONFIG.
*
* PIN_FUNC_ID format:
* Default:
@@ -545,18 +491,12 @@ static void imx_pinctrl_parse_pin_mmio(struct imx_pinctrl *ipctl,
pin_mmio->mux_mode = be32_to_cpu(*list++);
pin_mmio->input_val = be32_to_cpu(*list++);
- if (info->generic_pinconf) {
- /* generic pin config decoded */
- pin_mmio->config = imx_pinconf_parse_generic_config(np, ipctl);
- } else {
- /* legacy pin config read from devicetree */
- config = be32_to_cpu(*list++);
+ config = be32_to_cpu(*list++);
- /* SION bit is in mux register */
- if (config & IMX_PAD_SION)
- pin_mmio->mux_mode |= IOMUXC_CONFIG_SION;
- pin_mmio->config = config & ~IMX_PAD_SION;
- }
+ /* SION bit is in mux register */
+ if (config & IMX_PAD_SION)
+ pin_mmio->mux_mode |= IOMUXC_CONFIG_SION;
+ pin_mmio->config = config & ~IMX_PAD_SION;
*list_p = list;
@@ -571,6 +511,7 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
{
const struct imx_pinctrl_soc_info *info = ipctl->info;
struct imx_pin *pin;
+ unsigned int *pins;
int size, pin_size;
const __be32 *list;
int i;
@@ -584,11 +525,8 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
else
pin_size = FSL_PIN_SIZE;
- if (info->generic_pinconf)
- pin_size -= 4;
-
/* Initialise group */
- grp->name = np->name;
+ grp->grp.name = np->name;
/*
* the binding format is fsl,pins = <PIN_FUNC_ID CONFIG ...>,
@@ -616,24 +554,22 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
return -EINVAL;
}
- grp->num_pins = size / pin_size;
- grp->data = devm_kcalloc(ipctl->dev,
- grp->num_pins, sizeof(struct imx_pin),
- GFP_KERNEL);
- grp->pins = devm_kcalloc(ipctl->dev,
- grp->num_pins, sizeof(unsigned int),
- GFP_KERNEL);
- if (!grp->pins || !grp->data)
+ grp->grp.npins = size / pin_size;
+ grp->data = devm_kcalloc(ipctl->dev, grp->grp.npins, sizeof(*pin), GFP_KERNEL);
+ if (!grp->data)
+ return -ENOMEM;
+
+ pins = devm_kcalloc(ipctl->dev, grp->grp.npins, sizeof(*pins), GFP_KERNEL);
+ if (!pins)
return -ENOMEM;
+ grp->grp.pins = pins;
- for (i = 0; i < grp->num_pins; i++) {
+ for (i = 0; i < grp->grp.npins; i++) {
pin = &((struct imx_pin *)(grp->data))[i];
if (info->flags & IMX_USE_SCU)
- imx_pinctrl_parse_pin_scu(ipctl, &grp->pins[i],
- pin, &list);
+ info->imx_pinctrl_parse_pin(ipctl, &pins[i], pin, &list);
else
- imx_pinctrl_parse_pin_mmio(ipctl, &grp->pins[i],
- pin, &list, np);
+ imx_pinctrl_parse_pin_mmio(ipctl, &pins[i], pin, &list, np);
}
return 0;
@@ -644,38 +580,50 @@ static int imx_pinctrl_parse_functions(struct device_node *np,
u32 index)
{
struct pinctrl_dev *pctl = ipctl->pctl;
- struct device_node *child;
- struct function_desc *func;
+ struct pinfunction *func;
struct group_desc *grp;
- u32 i = 0;
+ const char **group_names;
+ int ret;
+ u32 i;
dev_dbg(pctl->dev, "parse function(%d): %pOFn\n", index, np);
- func = pinmux_generic_get_function(pctl, index);
+ func = devm_kzalloc(ipctl->dev, sizeof(*func), GFP_KERNEL);
if (!func)
- return -EINVAL;
+ return -ENOMEM;
/* Initialise function */
func->name = np->name;
- func->num_group_names = of_get_child_count(np);
- if (func->num_group_names == 0) {
- dev_err(ipctl->dev, "no groups defined in %pOF\n", np);
+ func->ngroups = of_get_child_count(np);
+ if (func->ngroups == 0) {
+ dev_info(ipctl->dev, "no groups defined in %pOF\n", np);
return -EINVAL;
}
- func->group_names = devm_kcalloc(ipctl->dev, func->num_group_names,
- sizeof(char *), GFP_KERNEL);
- if (!func->group_names)
- return -ENOMEM;
-
- for_each_child_of_node(np, child) {
- func->group_names[i] = child->name;
- grp = devm_kzalloc(ipctl->dev, sizeof(struct group_desc),
- GFP_KERNEL);
+ group_names = devm_kcalloc(ipctl->dev, func->ngroups,
+ sizeof(*func->groups), GFP_KERNEL);
+ if (!group_names)
+ return -ENOMEM;
+ i = 0;
+ for_each_child_of_node_scoped(np, child)
+ group_names[i++] = child->name;
+ func->groups = group_names;
+
+ ret = pinmux_generic_add_pinfunction(pctl, func, NULL);
+ if (ret < 0)
+ return ret;
+
+ i = 0;
+ for_each_child_of_node_scoped(np, child) {
+ grp = devm_kzalloc(ipctl->dev, sizeof(*grp), GFP_KERNEL);
if (!grp)
return -ENOMEM;
mutex_lock(&ipctl->mutex);
+ /*
+ * FIXME: This should use pinctrl_generic_add_group() and not
+ * access the private radix tree directly.
+ */
radix_tree_insert(&pctl->pin_group_tree,
ipctl->group_index++, grp);
mutex_unlock(&ipctl->mutex);
@@ -693,15 +641,12 @@ static int imx_pinctrl_parse_functions(struct device_node *np,
*/
static bool imx_pinctrl_dt_is_flat_functions(struct device_node *np)
{
- struct device_node *function_np;
- struct device_node *pinctrl_np;
-
- for_each_child_of_node(np, function_np) {
- if (of_property_read_bool(function_np, "fsl,pins"))
+ for_each_child_of_node_scoped(np, function_np) {
+ if (of_property_present(function_np, "fsl,pins"))
return true;
- for_each_child_of_node(function_np, pinctrl_np) {
- if (of_property_read_bool(pinctrl_np, "fsl,pins"))
+ for_each_child_of_node_scoped(function_np, pinctrl_np) {
+ if (of_property_present(pinctrl_np, "fsl,pins"))
return false;
}
}
@@ -733,20 +678,6 @@ static int imx_pinctrl_probe_dt(struct platform_device *pdev,
}
}
- for (i = 0; i < nfuncs; i++) {
- struct function_desc *function;
-
- function = devm_kzalloc(&pdev->dev, sizeof(*function),
- GFP_KERNEL);
- if (!function)
- return -ENOMEM;
-
- mutex_lock(&ipctl->mutex);
- radix_tree_insert(&pctl->pin_function_tree, i, function);
- mutex_unlock(&ipctl->mutex);
- }
- pctl->num_functions = nfuncs;
-
ipctl->group_index = 0;
if (flat_funcs) {
pctl->num_groups = of_get_child_count(np);
@@ -767,16 +698,6 @@ static int imx_pinctrl_probe_dt(struct platform_device *pdev,
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,
const struct imx_pinctrl_soc_info *info)
{
@@ -785,7 +706,6 @@ int imx_pinctrl_probe(struct platform_device *pdev,
struct pinctrl_desc *imx_pinctrl_desc;
struct device_node *np;
struct imx_pinctrl *ipctl;
- struct resource *res;
struct regmap *gpr;
int ret, i;
@@ -817,12 +737,11 @@ int imx_pinctrl_probe(struct platform_device *pdev,
ipctl->pin_regs[i].conf_reg = -1;
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- ipctl->base = devm_ioremap_resource(&pdev->dev, res);
+ ipctl->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(ipctl->base))
return PTR_ERR(ipctl->base);
- if (of_property_read_bool(dev_np, "fsl,input-sel")) {
+ if (of_property_present(dev_np, "fsl,input-sel")) {
np = of_parse_phandle(dev_np, "fsl,input-sel", 0);
if (!np) {
dev_err(&pdev->dev, "iomuxc fsl,input-sel property not found\n");
@@ -852,10 +771,6 @@ int imx_pinctrl_probe(struct platform_device *pdev,
imx_pinctrl_desc->confops = &imx_pinconf_ops;
imx_pinctrl_desc->owner = THIS_MODULE;
- /* for generic pinconf */
- imx_pinctrl_desc->custom_params = info->custom_params;
- imx_pinctrl_desc->num_custom_params = info->num_custom_params;
-
/* platform specific callback */
imx_pmx_ops.gpio_set_direction = info->gpio_set_direction;
@@ -869,21 +784,40 @@ int imx_pinctrl_probe(struct platform_device *pdev,
&ipctl->pctl);
if (ret) {
dev_err(&pdev->dev, "could not register IMX pinctrl driver\n");
- goto free;
+ return ret;
}
ret = imx_pinctrl_probe_dt(pdev, ipctl);
if (ret) {
dev_err(&pdev->dev, "fail to probe dt properties\n");
- goto free;
+ return ret;
}
dev_info(&pdev->dev, "initialized IMX pinctrl driver\n");
return pinctrl_enable(ipctl->pctl);
+}
+EXPORT_SYMBOL_GPL(imx_pinctrl_probe);
-free:
- imx_free_resources(ipctl);
+static int imx_pinctrl_suspend(struct device *dev)
+{
+ struct imx_pinctrl *ipctl = dev_get_drvdata(dev);
+
+ return pinctrl_force_sleep(ipctl->pctl);
+}
+
+static int imx_pinctrl_resume(struct device *dev)
+{
+ struct imx_pinctrl *ipctl = dev_get_drvdata(dev);
- return ret;
+ return pinctrl_force_default(ipctl->pctl);
}
+
+const struct dev_pm_ops imx_pinctrl_pm_ops = {
+ LATE_SYSTEM_SLEEP_PM_OPS(imx_pinctrl_suspend, imx_pinctrl_resume)
+};
+EXPORT_SYMBOL_GPL(imx_pinctrl_pm_ops);
+
+MODULE_AUTHOR("Dong Aisheng <aisheng.dong@nxp.com>");
+MODULE_DESCRIPTION("NXP i.MX common pinctrl driver");
+MODULE_LICENSE("GPL v2");