[RFC PATCH v2 2/4] pinctrl: imx: add pinmux imx driver

Linus Walleij linus.walleij at linaro.org
Wed Dec 14 13:00:35 EST 2011


On Wed, Dec 14, 2011 at 5:03 PM, Dong Aisheng <b29396 at freescale.com> wrote:

> The driver contains the initial support for imx53 and
> imx6q.

Cool! Comments below...

> --- /dev/null
> +++ b/drivers/pinctrl/pinmux-imx-core.c

We should start naming these pinctrl-* rather than pinmux-*
so just rename it.

Until here it looks like business as usual..

> +#ifdef CONFIG_OF
> +static int __devinit imx_pmx_parse_functions(struct device_node *np,
> +                       struct imx_pinctrl_info *info, u32 num)
> +{
> +       struct imx_pmx_func *function;
> +       struct imx_pin_group *group;
> +       int ret, len;
> +
> +       dev_dbg(info->dev, "parse function %d\n", num);
> +
> +       group = &info->groups[num];
> +       function = &info->functions[num];
> +
> +       /* Initialise group */
> +       ret = of_property_read_string(np, "grp_name", &group->name);
> +       if (ret) {
> +               dev_err(info->dev, "failed to get grp_name\n");
> +               return ret;
> +       }
> +
> +       ret = of_property_read_u32(np, "num_pins", &group->num_pins);
> +       if (ret) {
> +               dev_err(info->dev, "failed to get num_pins\n");
> +               return ret;
> +       }
> +
> +       ret = of_property_read_u32(np, "num_mux", &group->num_mux);
> +       if (ret) {
> +               dev_err(info->dev, "failed to get num_mux\n");
> +               return ret;
> +       }
> +
> +       if (group->num_pins != group->num_mux)
> +               return -EINVAL;
> +
> +       group->pins = devm_kzalloc(info->dev, group->num_pins * sizeof(unsigned int),
> +                               GFP_KERNEL);
> +       group->mux_mode = devm_kzalloc(info->dev, group->num_mux * sizeof(unsigned int),
> +                               GFP_KERNEL);
> +       if (!group->pins || !group->mux_mode)
> +               return -ENOMEM;
> +
> +       /* sanity check */
> +       if (of_get_property(np, "grp_pins", &len) &&
> +               len != group->num_pins * sizeof(unsigned int)) {
> +               dev_err(info->dev, "wrong pins number?\n");
> +               return -EINVAL;
> +       }
> +
> +       if (of_get_property(np, "grp_mux", &len) &&
> +               len != group->num_mux * sizeof(unsigned int)) {
> +               dev_err(info->dev, "wrong pin mux number?\n");
> +               return -EINVAL;
> +       }
> +
> +       ret = of_property_read_u32_array(np, "grp_pins",
> +                       group->pins, group->num_pins);
> +       if (ret) {
> +               dev_err(info->dev, "failed to get grp_pins\n");
> +               return ret;
> +       }
> +
> +       ret = of_property_read_u32_array(np, "grp_mux",
> +                       group->mux_mode, group->num_mux);
> +       if (ret) {
> +               dev_err(info->dev, "failed to get grp_mux\n");
> +               return ret;
> +       }
> +
> +       /* Initialise function */
> +       ret = of_property_read_string(np, "func_name", &function->name);
> +       if (ret) {
> +               dev_err(info->dev, "failed to get func_name\n");
> +               return ret;
> +       }
> +
> +       function->groups = devm_kzalloc(info->dev, sizeof(char **), GFP_KERNEL);
> +       function->num_groups = 1;
> +       function->groups[0] = group->name;
> +
> +       dev_dbg(info->dev, "func_name %s grp_name %s num_groups %d\n",
> +                               function->name, function->groups[0],
> +                               function->num_groups);
> +
> +       return 0;
> +}
> +
> +static int __devinit imx_pmx_probe_dt(struct platform_device *pdev,
> +                               struct imx_pinctrl_info *info)
> +{
> +       struct device_node *np = pdev->dev.of_node;
> +       struct device_node *child = NULL;
> +       int ret, i;
> +       u32 nfuncs = 0;
> +
> +       if (!np)
> +               return -ENODEV;
> +
> +       nfuncs = of_get_child_number(np);
> +       if (nfuncs <= 0) {
> +               dev_err(&pdev->dev, "no functions defined\n");
> +               return -EINVAL;
> +       }
> +
> +       info->nfunctions = nfuncs;
> +       info->functions = devm_kzalloc(&pdev->dev, nfuncs * sizeof(struct imx_pmx_func),
> +                                       GFP_KERNEL);
> +       if (!info->functions)
> +               return -ENOMEM;
> +
> +       /* DT file only passes one group per one function */
> +       info->ngroups = nfuncs;
> +       info->groups = devm_kzalloc(&pdev->dev, nfuncs * sizeof(struct imx_pin_group),
> +                                       GFP_KERNEL);
> +       if (!info->groups)
> +               return -ENOMEM;
> +
> +       child = NULL;
> +       i = 0;
> +       for_each_child_of_node(np, child) {
> +               ret = imx_pmx_parse_functions(child, info, i++);
> +               if (ret) {
> +                       dev_err(&pdev->dev, "failed to parse function\n");
> +                       return ret;
> +               }
> +       }
> +
> +       return 0;
> +}
> +#else
> +static int __devinit imx_pmx_probe_dt(struct platform_device *pdev,
> +                               struct imx_pinctrl_info *info)
> +{
> +       return -ENODEV;
> +}
> +#endif

Looks clever to me! And I think we have agreed that this probing
must be inside each driver.

Can we have a look at the corresponding device tree?
(...)

> +++ b/drivers/pinctrl/pinmux-imx-core.h

Name this pinctrl-* too for consistency.

(...)
> +#define IMX_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin)

Now I start to think about the range generators I discussed with
Haojian... but there doesn't seem to be very many ranges in this
driver so I guess it would only confuse things.

> +#define IMX_PIN_GROUP(n, p, m)  \
> +       {                       \
> +               .name = n,      \
> +               .pins = p,      \
> +               .num_pins = ARRAY_SIZE(p),      \
> +               .mux_mode = m,  \
> +               .num_mux = ARRAY_SIZE(m),       \
> +       }
> +
> +#define IMX_PMX_FUNC(n, g)  \
> +       {                       \
> +               .name = n,      \
> +               .groups = g,    \
> +               .num_groups = ARRAY_SIZE(g),    \
> +       }

This looks pretty smart!

> +++ b/drivers/pinctrl/pinmux-imx53.c

Name this pinctrl-*

> diff --git a/drivers/pinctrl/pinmux-imx6q.c b/drivers/pinctrl/pinmux-imx6q.c

This too.

This patch is overall very good, we're quickly approaching merge quality.

Yours,
Linus Walleij



More information about the linux-arm-kernel mailing list