db9662bef6a33bb35a7253c93b20639bdfba2895
[openwrt.git] / target / linux / lantiq / patches-3.7 / 0108-PINCTRL-lantiq-fixes.patch
1 From 13e754b5fff5be1930e2b8fe534a52b608c9e479 Mon Sep 17 00:00:00 2001
2 From: John Crispin <blogic@openwrt.org>
3 Date: Mon, 3 Dec 2012 19:27:28 +0100
4 Subject: [PATCH] PINCTRL: lantiq: fixes
5
6 ---
7  drivers/pinctrl/pinctrl-lantiq.c |   54 ++++++++++++++++++-----------
8  drivers/pinctrl/pinctrl-lantiq.h |    1 +
9  drivers/pinctrl/pinctrl-xway.c   |   70 ++++++++++++++++++++++++++++++++++----
10  3 files changed, 99 insertions(+), 26 deletions(-)
11
12 --- a/drivers/pinctrl/pinctrl-lantiq.c
13 +++ b/drivers/pinctrl/pinctrl-lantiq.c
14 @@ -64,11 +64,13 @@ static void ltq_pinctrl_pin_dbg_show(str
15         seq_printf(s, " %s", dev_name(pctldev->dev));
16  }
17  
18 -static int ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
19 +static void ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
20                                 struct device_node *np,
21                                 struct pinctrl_map **map)
22  {
23         struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev);
24 +       struct property *pins = of_find_property(np, "lantiq,pins", NULL);
25 +       struct property *groups = of_find_property(np, "lantiq,groups", NULL);
26         unsigned long configs[3];
27         unsigned num_configs = 0;
28         struct property *prop;
29 @@ -76,8 +78,20 @@ static int ltq_pinctrl_dt_subnode_to_map
30         const char *function;
31         int ret, i;
32  
33 +       if (!pins && !groups) {
34 +               dev_err(pctldev->dev, "%s defines neither pins nor groups\n",
35 +                       np->name);
36 +               return;
37 +       }
38 +
39 +       if (pins && groups) {
40 +               dev_err(pctldev->dev, "%s defines both pins and groups\n",
41 +                       np->name);
42 +               return;
43 +       }
44 +
45         ret = of_property_read_string(np, "lantiq,function", &function);
46 -       if (!ret) {
47 +       if (groups && !ret) {
48                 of_property_for_each_string(np, "lantiq,groups", prop, group) {
49                         (*map)->type = PIN_MAP_TYPE_MUX_GROUP;
50                         (*map)->name = function;
51 @@ -85,11 +99,6 @@ static int ltq_pinctrl_dt_subnode_to_map
52                         (*map)->data.mux.function = function;
53                         (*map)++;
54                 }
55 -               if (of_find_property(np, "lantiq,pins", NULL))
56 -                       dev_err(pctldev->dev,
57 -                               "%s mixes pins and groups settings\n",
58 -                               np->name);
59 -               return 0;
60         }
61  
62         for (i = 0; i < info->num_params; i++) {
63 @@ -103,7 +112,7 @@ static int ltq_pinctrl_dt_subnode_to_map
64         }
65  
66         if (!num_configs)
67 -               return -EINVAL;
68 +               return;
69  
70         of_property_for_each_string(np, "lantiq,pins", prop, pin) {
71                 (*map)->data.configs.configs = kmemdup(configs,
72 @@ -115,7 +124,16 @@ static int ltq_pinctrl_dt_subnode_to_map
73                 (*map)->data.configs.num_configs = num_configs;
74                 (*map)++;
75         }
76 -       return 0;
77 +       of_property_for_each_string(np, "lantiq,groups", prop, group) {
78 +               (*map)->data.configs.configs = kmemdup(configs,
79 +                                       num_configs * sizeof(unsigned long),
80 +                                       GFP_KERNEL);
81 +               (*map)->type = PIN_MAP_TYPE_CONFIGS_GROUP;
82 +               (*map)->name = group;
83 +               (*map)->data.configs.group_or_pin = group;
84 +               (*map)->data.configs.num_configs = num_configs;
85 +               (*map)++;
86 +       }
87  }
88  
89  static int ltq_pinctrl_dt_subnode_size(struct device_node *np)
90 @@ -135,23 +153,19 @@ int ltq_pinctrl_dt_node_to_map(struct pi
91  {
92         struct pinctrl_map *tmp;
93         struct device_node *np;
94 -       int ret;
95 +       int max_maps = 0;
96  
97 -       *num_maps = 0;
98         for_each_child_of_node(np_config, np)
99 -               *num_maps += ltq_pinctrl_dt_subnode_size(np);
100 -       *map = kzalloc(*num_maps * sizeof(struct pinctrl_map), GFP_KERNEL);
101 +               max_maps += ltq_pinctrl_dt_subnode_size(np);
102 +       *map = kzalloc(max_maps * sizeof(struct pinctrl_map) * 2, GFP_KERNEL);
103         if (!*map)
104                 return -ENOMEM;
105         tmp = *map;
106  
107 -       for_each_child_of_node(np_config, np) {
108 -               ret = ltq_pinctrl_dt_subnode_to_map(pctldev, np, &tmp);
109 -               if (ret < 0) {
110 -                       ltq_pinctrl_dt_free_map(pctldev, *map, *num_maps);
111 -                       return ret;
112 -               }
113 -       }
114 +       for_each_child_of_node(np_config, np)
115 +               ltq_pinctrl_dt_subnode_to_map(pctldev, np, &tmp);
116 +       *num_maps = ((int)(tmp - *map));
117 +
118         return 0;
119  }
120  
121 --- a/drivers/pinctrl/pinctrl-lantiq.h
122 +++ b/drivers/pinctrl/pinctrl-lantiq.h
123 @@ -34,6 +34,7 @@ enum ltq_pinconf_param {
124         LTQ_PINCONF_PARAM_OPEN_DRAIN,
125         LTQ_PINCONF_PARAM_DRIVE_CURRENT,
126         LTQ_PINCONF_PARAM_SLEW_RATE,
127 +       LTQ_PINCONF_PARAM_OUTPUT,
128  };
129  
130  struct ltq_cfg_param {
131 --- a/drivers/pinctrl/pinctrl-xway.c
132 +++ b/drivers/pinctrl/pinctrl-xway.c
133 @@ -443,7 +443,7 @@ static int xway_pinconf_get(struct pinct
134                 else
135                         reg = GPIO_OD(pin);
136                 *config = LTQ_PINCONF_PACK(param,
137 -                       !!gpio_getbit(info->membase[0], reg, PORT_PIN(pin)));
138 +                       !gpio_getbit(info->membase[0], reg, PORT_PIN(pin)));
139                 break;
140  
141         case LTQ_PINCONF_PARAM_PULL:
142 @@ -466,6 +466,11 @@ static int xway_pinconf_get(struct pinct
143                         *config = LTQ_PINCONF_PACK(param, 1);
144                 break;
145  
146 +       case LTQ_PINCONF_PARAM_OUTPUT:
147 +               reg = GPIO_DIR(pin);
148 +               *config = LTQ_PINCONF_PACK(param,
149 +                       gpio_getbit(info->membase[0], reg, PORT_PIN(pin)));
150 +               break;
151         default:
152                 dev_err(pctldev->dev, "Invalid config param %04x\n", param);
153                 return -ENOTSUPP;
154 @@ -489,7 +494,10 @@ static int xway_pinconf_set(struct pinct
155                         reg = GPIO3_OD;
156                 else
157                         reg = GPIO_OD(pin);
158 -               gpio_setbit(info->membase[0], reg, PORT_PIN(pin));
159 +               if (arg == 0)
160 +                       gpio_setbit(info->membase[0], reg, PORT_PIN(pin));
161 +               else
162 +                       gpio_clearbit(info->membase[0], reg, PORT_PIN(pin));
163                 break;
164  
165         case LTQ_PINCONF_PARAM_PULL:
166 @@ -515,6 +523,14 @@ static int xway_pinconf_set(struct pinct
167                         dev_err(pctldev->dev, "Invalid pull value %d\n", arg);
168                 break;
169  
170 +       case LTQ_PINCONF_PARAM_OUTPUT:
171 +               reg = GPIO_DIR(pin);
172 +               if (arg == 0)
173 +                       gpio_clearbit(info->membase[0], reg, PORT_PIN(pin));
174 +               else
175 +                       gpio_setbit(info->membase[0], reg, PORT_PIN(pin));
176 +               break;
177 +
178         default:
179                 dev_err(pctldev->dev, "Invalid config param %04x\n", param);
180                 return -ENOTSUPP;
181 @@ -522,9 +538,25 @@ static int xway_pinconf_set(struct pinct
182         return 0;
183  }
184  
185 +int xway_pinconf_group_set(struct pinctrl_dev *pctldev,
186 +                       unsigned selector,
187 +                       unsigned long config)
188 +{
189 +       struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctldev);
190 +       int i, ret = 0;
191 +
192 +       for (i = 0; i < info->grps[selector].npins && !ret; i++)
193 +               ret = xway_pinconf_set(pctldev,
194 +                                       info->grps[selector].pins[i], config);
195 +
196 +       return ret;
197 +}
198 +
199 +
200  struct pinconf_ops xway_pinconf_ops = {
201         .pin_config_get = xway_pinconf_get,
202         .pin_config_set = xway_pinconf_set,
203 +       .pin_config_group_set = xway_pinconf_group_set,
204  };
205  
206  static struct pinctrl_desc xway_pctrl_desc = {
207 @@ -532,10 +564,9 @@ static struct pinctrl_desc xway_pctrl_de
208         .confops        = &xway_pinconf_ops,
209  };
210  
211 -static inline int xway_mux_apply(struct pinctrl_dev *pctrldev,
212 +static int mux_apply(struct ltq_pinmux_info *info,
213                                 int pin, int mux)
214  {
215 -       struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
216         int port = PORT(pin);
217         u32 alt1_reg = GPIO_ALT1(pin);
218  
219 @@ -555,9 +586,18 @@ static inline int xway_mux_apply(struct
220         return 0;
221  }
222  
223 +static inline int xway_mux_apply(struct pinctrl_dev *pctrldev,
224 +                               int pin, int mux)
225 +{
226 +       struct ltq_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
227 +
228 +       return mux_apply(info, pin, mux);
229 +}
230 +
231  static const struct ltq_cfg_param xway_cfg_params[] = {
232         {"lantiq,pull",         LTQ_PINCONF_PARAM_PULL},
233         {"lantiq,open-drain",   LTQ_PINCONF_PARAM_OPEN_DRAIN},
234 +       {"lantiq,output",       LTQ_PINCONF_PARAM_OUTPUT},
235  };
236  
237  static struct ltq_pinmux_info xway_info = {
238 @@ -598,6 +638,10 @@ static int xway_gpio_dir_out(struct gpio
239  {
240         struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
241  
242 +       if (PORT(pin) == PORT3)
243 +               gpio_setbit(info->membase[0], GPIO3_OD, PORT_PIN(pin));
244 +       else
245 +               gpio_setbit(info->membase[0], GPIO_OD(pin), PORT_PIN(pin));
246         gpio_setbit(info->membase[0], GPIO_DIR(pin), PORT_PIN(pin));
247         xway_gpio_set(chip, pin, val);
248  
249 @@ -618,6 +662,18 @@ static void xway_gpio_free(struct gpio_c
250         pinctrl_free_gpio(gpio);
251  }
252  
253 +static int xway_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
254 +{
255 +       struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
256 +       int i;
257 +
258 +       for (i = 0; i < info->num_exin; i++)
259 +               if (info->exin[i] == offset)
260 +                       return ltq_eiu_get_irq(i);
261 +
262 +       return -1;
263 +}
264 +
265  static struct gpio_chip xway_chip = {
266         .label = "gpio-xway",
267         .direction_input = xway_gpio_dir_in,
268 @@ -626,6 +682,7 @@ static struct gpio_chip xway_chip = {
269         .set = xway_gpio_set,
270         .request = xway_gpio_req,
271         .free = xway_gpio_free,
272 +       .to_irq = xway_gpio_to_irq,
273         .base = -1,
274  };
275