aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/lantiq/patches-3.7/0108-PINCTRL-lantiq-fixes.patch
diff options
context:
space:
mode:
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.patch281
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,
+ };
+