diff options
Diffstat (limited to 'target/linux/lantiq/patches-3.7/0108-PINCTRL-lantiq-fixes.patch')
-rw-r--r-- | target/linux/lantiq/patches-3.7/0108-PINCTRL-lantiq-fixes.patch | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/target/linux/lantiq/patches-3.7/0108-PINCTRL-lantiq-fixes.patch b/target/linux/lantiq/patches-3.7/0108-PINCTRL-lantiq-fixes.patch new file mode 100644 index 0000000000..9ce8a785f9 --- /dev/null +++ b/target/linux/lantiq/patches-3.7/0108-PINCTRL-lantiq-fixes.patch @@ -0,0 +1,281 @@ +From 13e754b5fff5be1930e2b8fe534a52b608c9e479 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Mon, 3 Dec 2012 19:27:28 +0100 +Subject: [PATCH] PINCTRL: lantiq: fixes + +--- + drivers/pinctrl/pinctrl-lantiq.c | 54 ++++++++++++++++++----------- + drivers/pinctrl/pinctrl-lantiq.h | 1 + + drivers/pinctrl/pinctrl-xway.c | 70 ++++++++++++++++++++++++++++++++++---- + 3 files changed, 99 insertions(+), 26 deletions(-) + +Index: linux-3.7-rc8/drivers/pinctrl/pinctrl-lantiq.c +=================================================================== +--- linux-3.7-rc8.orig/drivers/pinctrl/pinctrl-lantiq.c 2012-12-03 20:22:37.000000000 +0100 ++++ linux-3.7-rc8/drivers/pinctrl/pinctrl-lantiq.c 2012-12-14 22:59:40.687563565 +0100 +@@ -64,11 +64,13 @@ + seq_printf(s, " %s", dev_name(pctldev->dev)); + } + +-static int ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, ++static void ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, + struct device_node *np, + struct pinctrl_map **map) + { + struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev); ++ struct property *pins = of_find_property(np, "lantiq,pins", NULL); ++ struct property *groups = of_find_property(np, "lantiq,groups", NULL); + unsigned long configs[3]; + unsigned num_configs = 0; + struct property *prop; +@@ -76,8 +78,20 @@ + const char *function; + int ret, i; + ++ if (!pins && !groups) { ++ dev_err(pctldev->dev, "%s defines neither pins nor groups\n", ++ np->name); ++ return; ++ } ++ ++ if (pins && groups) { ++ dev_err(pctldev->dev, "%s defines both pins and groups\n", ++ np->name); ++ return; ++ } ++ + ret = of_property_read_string(np, "lantiq,function", &function); +- if (!ret) { ++ if (groups && !ret) { + of_property_for_each_string(np, "lantiq,groups", prop, group) { + (*map)->type = PIN_MAP_TYPE_MUX_GROUP; + (*map)->name = function; +@@ -85,11 +99,6 @@ + (*map)->data.mux.function = function; + (*map)++; + } +- if (of_find_property(np, "lantiq,pins", NULL)) +- dev_err(pctldev->dev, +- "%s mixes pins and groups settings\n", +- np->name); +- return 0; + } + + for (i = 0; i < info->num_params; i++) { +@@ -103,7 +112,7 @@ + } + + if (!num_configs) +- return -EINVAL; ++ return; + + of_property_for_each_string(np, "lantiq,pins", prop, pin) { + (*map)->data.configs.configs = kmemdup(configs, +@@ -115,7 +124,16 @@ + (*map)->data.configs.num_configs = num_configs; + (*map)++; + } +- return 0; ++ of_property_for_each_string(np, "lantiq,groups", prop, group) { ++ (*map)->data.configs.configs = kmemdup(configs, ++ num_configs * sizeof(unsigned long), ++ GFP_KERNEL); ++ (*map)->type = PIN_MAP_TYPE_CONFIGS_GROUP; ++ (*map)->name = group; ++ (*map)->data.configs.group_or_pin = group; ++ (*map)->data.configs.num_configs = num_configs; ++ (*map)++; ++ } + } + + static int ltq_pinctrl_dt_subnode_size(struct device_node *np) +@@ -135,23 +153,19 @@ + { + struct pinctrl_map *tmp; + struct device_node *np; +- int ret; ++ int max_maps = 0; + +- *num_maps = 0; + for_each_child_of_node(np_config, np) +- *num_maps += ltq_pinctrl_dt_subnode_size(np); +- *map = kzalloc(*num_maps * sizeof(struct pinctrl_map), GFP_KERNEL); ++ max_maps += ltq_pinctrl_dt_subnode_size(np); ++ *map = kzalloc(max_maps * sizeof(struct pinctrl_map) * 2, GFP_KERNEL); + if (!*map) + return -ENOMEM; + tmp = *map; + +- for_each_child_of_node(np_config, np) { +- ret = ltq_pinctrl_dt_subnode_to_map(pctldev, np, &tmp); +- if (ret < 0) { +- ltq_pinctrl_dt_free_map(pctldev, *map, *num_maps); +- return ret; +- } +- } ++ for_each_child_of_node(np_config, np) ++ ltq_pinctrl_dt_subnode_to_map(pctldev, np, &tmp); ++ *num_maps = ((int)(tmp - *map)); ++ + return 0; + } + +Index: linux-3.7-rc8/drivers/pinctrl/pinctrl-lantiq.h +=================================================================== +--- linux-3.7-rc8.orig/drivers/pinctrl/pinctrl-lantiq.h 2012-12-03 20:22:37.000000000 +0100 ++++ linux-3.7-rc8/drivers/pinctrl/pinctrl-lantiq.h 2012-12-14 22:55:26.591557194 +0100 +@@ -34,6 +34,7 @@ + LTQ_PINCONF_PARAM_OPEN_DRAIN, + LTQ_PINCONF_PARAM_DRIVE_CURRENT, + LTQ_PINCONF_PARAM_SLEW_RATE, ++ LTQ_PINCONF_PARAM_OUTPUT, + }; + + struct ltq_cfg_param { +Index: linux-3.7-rc8/drivers/pinctrl/pinctrl-xway.c +=================================================================== +--- linux-3.7-rc8.orig/drivers/pinctrl/pinctrl-xway.c 2012-12-14 22:55:26.567557195 +0100 ++++ linux-3.7-rc8/drivers/pinctrl/pinctrl-xway.c 2012-12-14 22:55:26.595557195 +0100 +@@ -443,7 +443,7 @@ + else + reg = GPIO_OD(pin); + *config = LTQ_PINCONF_PACK(param, +- !!gpio_getbit(info->membase[0], reg, PORT_PIN(pin))); ++ !gpio_getbit(info->membase[0], reg, PORT_PIN(pin))); + break; + + case LTQ_PINCONF_PARAM_PULL: +@@ -466,6 +466,11 @@ + *config = LTQ_PINCONF_PACK(param, 1); + break; + ++ case LTQ_PINCONF_PARAM_OUTPUT: ++ reg = GPIO_DIR(pin); ++ *config = LTQ_PINCONF_PACK(param, ++ gpio_getbit(info->membase[0], reg, PORT_PIN(pin))); ++ break; + default: + dev_err(pctldev->dev, "Invalid config param %04x\n", param); + return -ENOTSUPP; +@@ -489,7 +494,10 @@ + reg = GPIO3_OD; + else + reg = GPIO_OD(pin); +- gpio_setbit(info->membase[0], reg, PORT_PIN(pin)); ++ if (arg == 0) ++ gpio_setbit(info->membase[0], reg, PORT_PIN(pin)); ++ else ++ gpio_clearbit(info->membase[0], reg, PORT_PIN(pin)); + break; + + case LTQ_PINCONF_PARAM_PULL: +@@ -515,6 +523,14 @@ + dev_err(pctldev->dev, "Invalid pull value %d\n", arg); + break; + ++ case LTQ_PINCONF_PARAM_OUTPUT: ++ reg = GPIO_DIR(pin); ++ if (arg == 0) ++ gpio_clearbit(info->membase[0], reg, PORT_PIN(pin)); ++ else ++ gpio_setbit(info->membase[0], reg, PORT_PIN(pin)); ++ break; ++ + default: + dev_err(pctldev->dev, "Invalid config param %04x\n", param); + return -ENOTSUPP; +@@ -522,9 +538,25 @@ + return 0; + } + ++int xway_pinconf_group_set(struct pinctrl_dev *pctldev, ++ unsigned selector, ++ unsigned long config) ++{ ++ struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev); ++ int i, ret = 0; ++ ++ for (i = 0; i < info->grps[selector].npins && !ret; i++) ++ ret = xway_pinconf_set(pctldev, ++ info->grps[selector].pins[i], config); ++ ++ return ret; ++} ++ ++ + struct pinconf_ops xway_pinconf_ops = { + .pin_config_get = xway_pinconf_get, + .pin_config_set = xway_pinconf_set, ++ .pin_config_group_set = xway_pinconf_group_set, + }; + + static struct pinctrl_desc xway_pctrl_desc = { +@@ -532,10 +564,9 @@ + .confops = &xway_pinconf_ops, + }; + +-static inline int xway_mux_apply(struct pinctrl_dev *pctrldev, ++static int mux_apply(struct ltq_pinmux_info *info, + int pin, int mux) + { +- struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev); + int port = PORT(pin); + u32 alt1_reg = GPIO_ALT1(pin); + +@@ -555,9 +586,18 @@ + return 0; + } + ++static inline int xway_mux_apply(struct pinctrl_dev *pctrldev, ++ int pin, int mux) ++{ ++ struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev); ++ ++ return mux_apply(info, pin, mux); ++} ++ + static const struct ltq_cfg_param xway_cfg_params[] = { + {"lantiq,pull", LTQ_PINCONF_PARAM_PULL}, + {"lantiq,open-drain", LTQ_PINCONF_PARAM_OPEN_DRAIN}, ++ {"lantiq,output", LTQ_PINCONF_PARAM_OUTPUT}, + }; + + static struct ltq_pinmux_info xway_info = { +@@ -598,6 +638,10 @@ + { + struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev); + ++ if (PORT(pin) == PORT3) ++ gpio_setbit(info->membase[0], GPIO3_OD, PORT_PIN(pin)); ++ else ++ gpio_setbit(info->membase[0], GPIO_OD(pin), PORT_PIN(pin)); + gpio_setbit(info->membase[0], GPIO_DIR(pin), PORT_PIN(pin)); + xway_gpio_set(chip, pin, val); + +@@ -618,6 +662,18 @@ + pinctrl_free_gpio(gpio); + } + ++static int xway_gpio_to_irq(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev); ++ int i; ++ ++ for (i = 0; i < info->num_exin; i++) ++ if (info->exin[i] == offset) ++ return ltq_eiu_get_irq(i); ++ ++ return -1; ++} ++ + static struct gpio_chip xway_chip = { + .label = "gpio-xway", + .direction_input = xway_gpio_dir_in, +@@ -626,6 +682,7 @@ + .set = xway_gpio_set, + .request = xway_gpio_req, + .free = xway_gpio_free, ++ .to_irq = xway_gpio_to_irq, + .base = -1, + }; + |