diff options
Diffstat (limited to 'target/linux/sunxi/patches-4.9/0034-pinctrl-sunxi-Deal-with-configless-pins.patch')
-rw-r--r-- | target/linux/sunxi/patches-4.9/0034-pinctrl-sunxi-Deal-with-configless-pins.patch | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/target/linux/sunxi/patches-4.9/0034-pinctrl-sunxi-Deal-with-configless-pins.patch b/target/linux/sunxi/patches-4.9/0034-pinctrl-sunxi-Deal-with-configless-pins.patch new file mode 100644 index 0000000000..119ab2b8f9 --- /dev/null +++ b/target/linux/sunxi/patches-4.9/0034-pinctrl-sunxi-Deal-with-configless-pins.patch @@ -0,0 +1,128 @@ +From e11dee2e98f8abc99ad5336796576a827853ccfa Mon Sep 17 00:00:00 2001 +From: Maxime Ripard <maxime.ripard@free-electrons.com> +Date: Thu, 20 Oct 2016 15:49:02 +0200 +Subject: pinctrl: sunxi: Deal with configless pins + +Even though the our binding had the assumption that the allwinner,pull and +allwinner,drive properties were optional, the code never took that into +account. + +Fix that. + +Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> +Acked-by: Chen-Yu Tsai <wens@csie.org> +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +--- + drivers/pinctrl/sunxi/pinctrl-sunxi.c | 51 +++++++++++++++++++++++++---------- + 1 file changed, 37 insertions(+), 14 deletions(-) + +--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c ++++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c +@@ -261,20 +261,29 @@ static unsigned long *sunxi_pctrl_build_ + { + unsigned long *pinconfig; + unsigned int configlen = 0, idx = 0; ++ int ret; + + if (sunxi_pctrl_has_drive_prop(node)) + configlen++; + if (sunxi_pctrl_has_bias_prop(node)) + configlen++; + ++ /* ++ * If we don't have any configuration, bail out ++ */ ++ if (!configlen) ++ return NULL; ++ + pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL); + if (!pinconfig) +- return NULL; ++ return ERR_PTR(-ENOMEM); + + if (sunxi_pctrl_has_drive_prop(node)) { + int drive = sunxi_pctrl_parse_drive_prop(node); +- if (drive < 0) ++ if (drive < 0) { ++ ret = drive; + goto err_free; ++ } + + pinconfig[idx++] = pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH, + drive); +@@ -282,8 +291,10 @@ static unsigned long *sunxi_pctrl_build_ + + if (sunxi_pctrl_has_bias_prop(node)) { + int pull = sunxi_pctrl_parse_bias_prop(node); +- if (pull < 0) ++ if (pull < 0) { ++ ret = pull; + goto err_free; ++ } + + pinconfig[idx++] = pinconf_to_config_packed(pull, 0); + } +@@ -294,7 +305,7 @@ static unsigned long *sunxi_pctrl_build_ + + err_free: + kfree(pinconfig); +- return NULL; ++ return ERR_PTR(ret); + } + + static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, +@@ -328,7 +339,10 @@ static int sunxi_pctrl_dt_node_to_map(st + + /* + * We have two maps for each pin: one for the function, one +- * for the configuration (bias, strength, etc) ++ * for the configuration (bias, strength, etc). ++ * ++ * We might be slightly overshooting, since we might not have ++ * any configuration. + */ + nmaps = npins * 2; + *map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL); +@@ -336,8 +350,8 @@ static int sunxi_pctrl_dt_node_to_map(st + return -ENOMEM; + + pinconfig = sunxi_pctrl_build_pin_config(node, &configlen); +- if (!pinconfig) { +- ret = -EINVAL; ++ if (IS_ERR(pinconfig)) { ++ ret = PTR_ERR(pinconfig); + goto err_free_map; + } + +@@ -364,15 +378,24 @@ static int sunxi_pctrl_dt_node_to_map(st + + i++; + +- (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP; +- (*map)[i].data.configs.group_or_pin = group; +- (*map)[i].data.configs.configs = pinconfig; +- (*map)[i].data.configs.num_configs = configlen; +- +- i++; ++ if (pinconfig) { ++ (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP; ++ (*map)[i].data.configs.group_or_pin = group; ++ (*map)[i].data.configs.configs = pinconfig; ++ (*map)[i].data.configs.num_configs = configlen; ++ i++; ++ } + } + +- *num_maps = nmaps; ++ *num_maps = i; ++ ++ /* ++ * We know have the number of maps we need, we can resize our ++ * map array ++ */ ++ *map = krealloc(*map, i * sizeof(struct pinctrl_map), GFP_KERNEL); ++ if (!map) ++ return -ENOMEM; + + return 0; + |