34a422794d
This backports multiple patches from kernel 4.10 which are adding missing support for the A64 and the pine64 board. These are the device tree files, the pinctlk and the clock driver. Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
128 lines
3.4 KiB
Diff
128 lines
3.4 KiB
Diff
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;
|
|
|