Commit 63d2059c authored by Frank Li's avatar Frank Li Committed by Linus Walleij
Browse files

pinctrl: imx1: Allow parsing DT without function nodes



The old format to define pinctrl settings for imx in DT has two hierarchy
levels. The first level are function device nodes. The second level are
pingroups which contain a property fsl,pins. The original ntention was to
define all pin functions in a single dtsi file and just reference the
correct ones in the board files.

The commit ("5fcdf6a7 pinctrl: imx: Allow parsing DT without function
nodes") already make moden i.MX chip support flatten layout.

Make legacy chipes (more than 15 years) support this flatten layout also.

Fixes: e948cbdc ("ARM: dts: imx: remove redundant intermediate node in pinmux hierarchy")
Tested-by: default avatarSébastien Szymanski <sebastien.szymanski@armadeus.com>
Signed-off-by: default avatarFrank Li <Frank.Li@nxp.com>
Signed-off-by: default avatarLinus Walleij <linusw@kernel.org>
parent 7cf4846a
Loading
Loading
Loading
Loading
+41 −7
Original line number Diff line number Diff line
@@ -540,10 +540,34 @@ static int imx1_pinctrl_parse_functions(struct device_node *np,
	return 0;
}

/*
 * Check if the DT contains pins in the direct child nodes. This indicates the
 * newer DT format to store pins. This function returns true if the first found
 * fsl,pins property is in a child of np. Otherwise false is returned.
 */
static bool imx1_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_present(function_np, "fsl,pins"))
			return true;

		for_each_child_of_node(function_np, pinctrl_np) {
			if (of_property_present(pinctrl_np, "fsl,pins"))
				return false;
		}
	}

	return true;
}

static int imx1_pinctrl_parse_dt(struct platform_device *pdev,
		struct imx1_pinctrl *pctl, struct imx1_pinctrl_soc_info *info)
{
	struct device_node *np = pdev->dev.of_node;
	bool flat_funcs;
	int ret;
	u32 nfuncs = 0;
	u32 ngroups = 0;
@@ -552,10 +576,16 @@ static int imx1_pinctrl_parse_dt(struct platform_device *pdev,
	if (!np)
		return -ENODEV;

	flat_funcs = imx1_pinctrl_dt_is_flat_functions(np);
	if (flat_funcs) {
		nfuncs = 1;
		ngroups = of_get_child_count(np);
	} else {
		for_each_child_of_node_scoped(np, child) {
			++nfuncs;
			ngroups += of_get_child_count(child);
		}
	}

	if (!nfuncs) {
		dev_err(&pdev->dev, "No pin functions defined\n");
@@ -574,11 +604,15 @@ static int imx1_pinctrl_parse_dt(struct platform_device *pdev,
	if (!info->functions || !info->groups)
		return -ENOMEM;

	if (flat_funcs) {
		imx1_pinctrl_parse_functions(np, info, 0);
	} else {
		for_each_child_of_node_scoped(np, child) {
			ret = imx1_pinctrl_parse_functions(child, info, ifunc++);
			if (ret == -ENOMEM)
				return -ENOMEM;
		}
	}

	return 0;
}