Commit | Line | Data |
---|---|---|
97fb5e8d | 1 | // SPDX-License-Identifier: GPL-2.0-only |
f365be09 BA |
2 | /* |
3 | * Copyright (c) 2013, Sony Mobile Communications AB. | |
4 | * Copyright (c) 2013, The Linux Foundation. All rights reserved. | |
f365be09 BA |
5 | */ |
6 | ||
32745581 | 7 | #include <linux/delay.h> |
f365be09 | 8 | #include <linux/err.h> |
f365be09 BA |
9 | #include <linux/io.h> |
10 | #include <linux/module.h> | |
11 | #include <linux/of.h> | |
12 | #include <linux/platform_device.h> | |
13 | #include <linux/pinctrl/machine.h> | |
14 | #include <linux/pinctrl/pinctrl.h> | |
15 | #include <linux/pinctrl/pinmux.h> | |
16 | #include <linux/pinctrl/pinconf.h> | |
17 | #include <linux/pinctrl/pinconf-generic.h> | |
18 | #include <linux/slab.h> | |
1c5fb66a | 19 | #include <linux/gpio/driver.h> |
f365be09 | 20 | #include <linux/interrupt.h> |
f365be09 | 21 | #include <linux/spinlock.h> |
cf1fc187 | 22 | #include <linux/reboot.h> |
ad644987 | 23 | #include <linux/pm.h> |
47a01ee9 | 24 | #include <linux/log2.h> |
32745581 | 25 | |
69b78b8d LW |
26 | #include "../core.h" |
27 | #include "../pinconf.h" | |
f365be09 | 28 | #include "pinctrl-msm.h" |
69b78b8d | 29 | #include "../pinctrl-utils.h" |
f365be09 | 30 | |
408e3c66 | 31 | #define MAX_NR_GPIO 300 |
a46d5e98 | 32 | #define MAX_NR_TILES 4 |
32745581 | 33 | #define PS_HOLD_OFFSET 0x820 |
408e3c66 | 34 | |
f365be09 BA |
35 | /** |
36 | * struct msm_pinctrl - state for a pinctrl-msm device | |
37 | * @dev: device handle. | |
38 | * @pctrl: pinctrl handle. | |
f365be09 | 39 | * @chip: gpiochip handle. |
cf1fc187 | 40 | * @restart_nb: restart notifier block. |
f365be09 BA |
41 | * @irq: parent irq for the TLMM irq_chip. |
42 | * @lock: Spinlock to protect register resources as well | |
43 | * as msm_pinctrl data structures. | |
44 | * @enabled_irqs: Bitmap of currently enabled irqs. | |
45 | * @dual_edge_irqs: Bitmap of irqs that need sw emulated dual edge | |
46 | * detection. | |
f365be09 | 47 | * @soc; Reference to soc_data of platform specific data. |
a46d5e98 | 48 | * @regs: Base addresses for the TLMM tiles. |
f365be09 BA |
49 | */ |
50 | struct msm_pinctrl { | |
51 | struct device *dev; | |
52 | struct pinctrl_dev *pctrl; | |
f365be09 | 53 | struct gpio_chip chip; |
f265e8b9 | 54 | struct pinctrl_desc desc; |
cf1fc187 | 55 | struct notifier_block restart_nb; |
f265e8b9 TT |
56 | |
57 | struct irq_chip irq_chip; | |
f393e489 | 58 | int irq; |
f365be09 | 59 | |
47b03ca9 | 60 | raw_spinlock_t lock; |
f365be09 | 61 | |
408e3c66 BA |
62 | DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO); |
63 | DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO); | |
f365be09 BA |
64 | |
65 | const struct msm_pinctrl_soc_data *soc; | |
a46d5e98 | 66 | void __iomem *regs[MAX_NR_TILES]; |
f365be09 BA |
67 | }; |
68 | ||
6c736989 BA |
69 | #define MSM_ACCESSOR(name) \ |
70 | static u32 msm_readl_##name(struct msm_pinctrl *pctrl, \ | |
71 | const struct msm_pingroup *g) \ | |
72 | { \ | |
a46d5e98 | 73 | return readl(pctrl->regs[g->tile] + g->name##_reg); \ |
6c736989 BA |
74 | } \ |
75 | static void msm_writel_##name(u32 val, struct msm_pinctrl *pctrl, \ | |
76 | const struct msm_pingroup *g) \ | |
77 | { \ | |
a46d5e98 | 78 | writel(val, pctrl->regs[g->tile] + g->name##_reg); \ |
6c736989 BA |
79 | } |
80 | ||
81 | MSM_ACCESSOR(ctl) | |
82 | MSM_ACCESSOR(io) | |
83 | MSM_ACCESSOR(intr_cfg) | |
84 | MSM_ACCESSOR(intr_status) | |
85 | MSM_ACCESSOR(intr_target) | |
86 | ||
f365be09 BA |
87 | static int msm_get_groups_count(struct pinctrl_dev *pctldev) |
88 | { | |
89 | struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); | |
90 | ||
91 | return pctrl->soc->ngroups; | |
92 | } | |
93 | ||
94 | static const char *msm_get_group_name(struct pinctrl_dev *pctldev, | |
95 | unsigned group) | |
96 | { | |
97 | struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); | |
98 | ||
99 | return pctrl->soc->groups[group].name; | |
100 | } | |
101 | ||
102 | static int msm_get_group_pins(struct pinctrl_dev *pctldev, | |
103 | unsigned group, | |
104 | const unsigned **pins, | |
105 | unsigned *num_pins) | |
106 | { | |
107 | struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); | |
108 | ||
109 | *pins = pctrl->soc->groups[group].pins; | |
110 | *num_pins = pctrl->soc->groups[group].npins; | |
111 | return 0; | |
112 | } | |
113 | ||
1f2b2398 | 114 | static const struct pinctrl_ops msm_pinctrl_ops = { |
f365be09 BA |
115 | .get_groups_count = msm_get_groups_count, |
116 | .get_group_name = msm_get_group_name, | |
117 | .get_group_pins = msm_get_group_pins, | |
118 | .dt_node_to_map = pinconf_generic_dt_node_to_map_group, | |
d32f7fd3 | 119 | .dt_free_map = pinctrl_utils_free_map, |
f365be09 BA |
120 | }; |
121 | ||
691bf5d5 SB |
122 | static int msm_pinmux_request(struct pinctrl_dev *pctldev, unsigned offset) |
123 | { | |
124 | struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); | |
125 | struct gpio_chip *chip = &pctrl->chip; | |
126 | ||
127 | return gpiochip_line_is_valid(chip, offset) ? 0 : -EINVAL; | |
128 | } | |
129 | ||
f365be09 BA |
130 | static int msm_get_functions_count(struct pinctrl_dev *pctldev) |
131 | { | |
132 | struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); | |
133 | ||
134 | return pctrl->soc->nfunctions; | |
135 | } | |
136 | ||
137 | static const char *msm_get_function_name(struct pinctrl_dev *pctldev, | |
138 | unsigned function) | |
139 | { | |
140 | struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); | |
141 | ||
142 | return pctrl->soc->functions[function].name; | |
143 | } | |
144 | ||
145 | static int msm_get_function_groups(struct pinctrl_dev *pctldev, | |
146 | unsigned function, | |
147 | const char * const **groups, | |
148 | unsigned * const num_groups) | |
149 | { | |
150 | struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); | |
151 | ||
152 | *groups = pctrl->soc->functions[function].groups; | |
153 | *num_groups = pctrl->soc->functions[function].ngroups; | |
154 | return 0; | |
155 | } | |
156 | ||
03e9f0ca LW |
157 | static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev, |
158 | unsigned function, | |
159 | unsigned group) | |
f365be09 BA |
160 | { |
161 | struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); | |
162 | const struct msm_pingroup *g; | |
163 | unsigned long flags; | |
47a01ee9 | 164 | u32 val, mask; |
f365be09 BA |
165 | int i; |
166 | ||
167 | g = &pctrl->soc->groups[group]; | |
47a01ee9 | 168 | mask = GENMASK(g->mux_bit + order_base_2(g->nfuncs) - 1, g->mux_bit); |
f365be09 | 169 | |
3c25381f | 170 | for (i = 0; i < g->nfuncs; i++) { |
f365be09 BA |
171 | if (g->funcs[i] == function) |
172 | break; | |
173 | } | |
174 | ||
3c25381f | 175 | if (WARN_ON(i == g->nfuncs)) |
f365be09 BA |
176 | return -EINVAL; |
177 | ||
47b03ca9 | 178 | raw_spin_lock_irqsave(&pctrl->lock, flags); |
f365be09 | 179 | |
6c736989 | 180 | val = msm_readl_ctl(pctrl, g); |
6bcf3f63 | 181 | val &= ~mask; |
f365be09 | 182 | val |= i << g->mux_bit; |
6c736989 | 183 | msm_writel_ctl(val, pctrl, g); |
f365be09 | 184 | |
47b03ca9 | 185 | raw_spin_unlock_irqrestore(&pctrl->lock, flags); |
f365be09 BA |
186 | |
187 | return 0; | |
188 | } | |
189 | ||
1de7ddb3 SB |
190 | static int msm_pinmux_request_gpio(struct pinctrl_dev *pctldev, |
191 | struct pinctrl_gpio_range *range, | |
192 | unsigned offset) | |
193 | { | |
194 | struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); | |
195 | const struct msm_pingroup *g = &pctrl->soc->groups[offset]; | |
196 | ||
197 | /* No funcs? Probably ACPI so can't do anything here */ | |
198 | if (!g->nfuncs) | |
199 | return 0; | |
200 | ||
201 | /* For now assume function 0 is GPIO because it always is */ | |
de0c18a8 | 202 | return msm_pinmux_set_mux(pctldev, g->funcs[0], offset); |
1de7ddb3 SB |
203 | } |
204 | ||
1f2b2398 | 205 | static const struct pinmux_ops msm_pinmux_ops = { |
691bf5d5 | 206 | .request = msm_pinmux_request, |
f365be09 BA |
207 | .get_functions_count = msm_get_functions_count, |
208 | .get_function_name = msm_get_function_name, | |
209 | .get_function_groups = msm_get_function_groups, | |
1de7ddb3 | 210 | .gpio_request_enable = msm_pinmux_request_gpio, |
03e9f0ca | 211 | .set_mux = msm_pinmux_set_mux, |
f365be09 BA |
212 | }; |
213 | ||
214 | static int msm_config_reg(struct msm_pinctrl *pctrl, | |
215 | const struct msm_pingroup *g, | |
216 | unsigned param, | |
f365be09 BA |
217 | unsigned *mask, |
218 | unsigned *bit) | |
219 | { | |
220 | switch (param) { | |
221 | case PIN_CONFIG_BIAS_DISABLE: | |
f365be09 | 222 | case PIN_CONFIG_BIAS_PULL_DOWN: |
b831a15e | 223 | case PIN_CONFIG_BIAS_BUS_HOLD: |
f365be09 | 224 | case PIN_CONFIG_BIAS_PULL_UP: |
f365be09 BA |
225 | *bit = g->pull_bit; |
226 | *mask = 3; | |
227 | break; | |
228 | case PIN_CONFIG_DRIVE_STRENGTH: | |
f365be09 BA |
229 | *bit = g->drv_bit; |
230 | *mask = 7; | |
231 | break; | |
ed118a5f | 232 | case PIN_CONFIG_OUTPUT: |
407f5e39 | 233 | case PIN_CONFIG_INPUT_ENABLE: |
ed118a5f BA |
234 | *bit = g->oe_bit; |
235 | *mask = 1; | |
236 | break; | |
f365be09 | 237 | default: |
f365be09 BA |
238 | return -ENOTSUPP; |
239 | } | |
240 | ||
f365be09 BA |
241 | return 0; |
242 | } | |
243 | ||
83cf5fae RCJ |
244 | #define MSM_NO_PULL 0 |
245 | #define MSM_PULL_DOWN 1 | |
246 | #define MSM_KEEPER 2 | |
247 | #define MSM_PULL_UP_NO_KEEPER 2 | |
248 | #define MSM_PULL_UP 3 | |
f365be09 | 249 | |
7cc34e2e SB |
250 | static unsigned msm_regval_to_drive(u32 val) |
251 | { | |
252 | return (val + 1) * 2; | |
253 | } | |
f365be09 BA |
254 | |
255 | static int msm_config_group_get(struct pinctrl_dev *pctldev, | |
256 | unsigned int group, | |
257 | unsigned long *config) | |
258 | { | |
259 | const struct msm_pingroup *g; | |
260 | struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); | |
261 | unsigned param = pinconf_to_config_param(*config); | |
262 | unsigned mask; | |
263 | unsigned arg; | |
264 | unsigned bit; | |
f365be09 BA |
265 | int ret; |
266 | u32 val; | |
267 | ||
268 | g = &pctrl->soc->groups[group]; | |
269 | ||
051a58b4 | 270 | ret = msm_config_reg(pctrl, g, param, &mask, &bit); |
f365be09 BA |
271 | if (ret < 0) |
272 | return ret; | |
273 | ||
6c736989 | 274 | val = msm_readl_ctl(pctrl, g); |
f365be09 BA |
275 | arg = (val >> bit) & mask; |
276 | ||
277 | /* Convert register value to pinconf value */ | |
278 | switch (param) { | |
279 | case PIN_CONFIG_BIAS_DISABLE: | |
05e0c828 DA |
280 | if (arg != MSM_NO_PULL) |
281 | return -EINVAL; | |
282 | arg = 1; | |
f365be09 BA |
283 | break; |
284 | case PIN_CONFIG_BIAS_PULL_DOWN: | |
05e0c828 DA |
285 | if (arg != MSM_PULL_DOWN) |
286 | return -EINVAL; | |
287 | arg = 1; | |
f365be09 | 288 | break; |
b831a15e | 289 | case PIN_CONFIG_BIAS_BUS_HOLD: |
83cf5fae RCJ |
290 | if (pctrl->soc->pull_no_keeper) |
291 | return -ENOTSUPP; | |
292 | ||
05e0c828 DA |
293 | if (arg != MSM_KEEPER) |
294 | return -EINVAL; | |
295 | arg = 1; | |
b831a15e | 296 | break; |
f365be09 | 297 | case PIN_CONFIG_BIAS_PULL_UP: |
83cf5fae RCJ |
298 | if (pctrl->soc->pull_no_keeper) |
299 | arg = arg == MSM_PULL_UP_NO_KEEPER; | |
300 | else | |
301 | arg = arg == MSM_PULL_UP; | |
05e0c828 DA |
302 | if (!arg) |
303 | return -EINVAL; | |
f365be09 BA |
304 | break; |
305 | case PIN_CONFIG_DRIVE_STRENGTH: | |
7cc34e2e | 306 | arg = msm_regval_to_drive(arg); |
f365be09 | 307 | break; |
ed118a5f BA |
308 | case PIN_CONFIG_OUTPUT: |
309 | /* Pin is not output */ | |
310 | if (!arg) | |
311 | return -EINVAL; | |
312 | ||
6c736989 | 313 | val = msm_readl_io(pctrl, g); |
ed118a5f BA |
314 | arg = !!(val & BIT(g->in_bit)); |
315 | break; | |
407f5e39 SV |
316 | case PIN_CONFIG_INPUT_ENABLE: |
317 | /* Pin is output */ | |
318 | if (arg) | |
319 | return -EINVAL; | |
320 | arg = 1; | |
321 | break; | |
f365be09 | 322 | default: |
38d756af | 323 | return -ENOTSUPP; |
f365be09 BA |
324 | } |
325 | ||
326 | *config = pinconf_to_config_packed(param, arg); | |
327 | ||
328 | return 0; | |
329 | } | |
330 | ||
331 | static int msm_config_group_set(struct pinctrl_dev *pctldev, | |
332 | unsigned group, | |
333 | unsigned long *configs, | |
334 | unsigned num_configs) | |
335 | { | |
336 | const struct msm_pingroup *g; | |
337 | struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); | |
338 | unsigned long flags; | |
339 | unsigned param; | |
340 | unsigned mask; | |
341 | unsigned arg; | |
342 | unsigned bit; | |
f365be09 BA |
343 | int ret; |
344 | u32 val; | |
345 | int i; | |
346 | ||
347 | g = &pctrl->soc->groups[group]; | |
348 | ||
349 | for (i = 0; i < num_configs; i++) { | |
350 | param = pinconf_to_config_param(configs[i]); | |
351 | arg = pinconf_to_config_argument(configs[i]); | |
352 | ||
051a58b4 | 353 | ret = msm_config_reg(pctrl, g, param, &mask, &bit); |
f365be09 BA |
354 | if (ret < 0) |
355 | return ret; | |
356 | ||
357 | /* Convert pinconf values to register values */ | |
358 | switch (param) { | |
359 | case PIN_CONFIG_BIAS_DISABLE: | |
360 | arg = MSM_NO_PULL; | |
361 | break; | |
362 | case PIN_CONFIG_BIAS_PULL_DOWN: | |
363 | arg = MSM_PULL_DOWN; | |
364 | break; | |
b831a15e | 365 | case PIN_CONFIG_BIAS_BUS_HOLD: |
83cf5fae RCJ |
366 | if (pctrl->soc->pull_no_keeper) |
367 | return -ENOTSUPP; | |
368 | ||
b831a15e AG |
369 | arg = MSM_KEEPER; |
370 | break; | |
f365be09 | 371 | case PIN_CONFIG_BIAS_PULL_UP: |
83cf5fae RCJ |
372 | if (pctrl->soc->pull_no_keeper) |
373 | arg = MSM_PULL_UP_NO_KEEPER; | |
374 | else | |
375 | arg = MSM_PULL_UP; | |
f365be09 BA |
376 | break; |
377 | case PIN_CONFIG_DRIVE_STRENGTH: | |
378 | /* Check for invalid values */ | |
7cc34e2e | 379 | if (arg > 16 || arg < 2 || (arg % 2) != 0) |
f365be09 BA |
380 | arg = -1; |
381 | else | |
7cc34e2e | 382 | arg = (arg / 2) - 1; |
f365be09 | 383 | break; |
ed118a5f BA |
384 | case PIN_CONFIG_OUTPUT: |
385 | /* set output value */ | |
47b03ca9 | 386 | raw_spin_lock_irqsave(&pctrl->lock, flags); |
6c736989 | 387 | val = msm_readl_io(pctrl, g); |
ed118a5f BA |
388 | if (arg) |
389 | val |= BIT(g->out_bit); | |
390 | else | |
391 | val &= ~BIT(g->out_bit); | |
6c736989 | 392 | msm_writel_io(val, pctrl, g); |
47b03ca9 | 393 | raw_spin_unlock_irqrestore(&pctrl->lock, flags); |
ed118a5f BA |
394 | |
395 | /* enable output */ | |
396 | arg = 1; | |
397 | break; | |
407f5e39 SV |
398 | case PIN_CONFIG_INPUT_ENABLE: |
399 | /* disable output */ | |
400 | arg = 0; | |
401 | break; | |
f365be09 BA |
402 | default: |
403 | dev_err(pctrl->dev, "Unsupported config parameter: %x\n", | |
404 | param); | |
405 | return -EINVAL; | |
406 | } | |
407 | ||
408 | /* Range-check user-supplied value */ | |
409 | if (arg & ~mask) { | |
410 | dev_err(pctrl->dev, "config %x: %x is invalid\n", param, arg); | |
411 | return -EINVAL; | |
412 | } | |
413 | ||
47b03ca9 | 414 | raw_spin_lock_irqsave(&pctrl->lock, flags); |
6c736989 | 415 | val = msm_readl_ctl(pctrl, g); |
f365be09 BA |
416 | val &= ~(mask << bit); |
417 | val |= arg << bit; | |
6c736989 | 418 | msm_writel_ctl(val, pctrl, g); |
47b03ca9 | 419 | raw_spin_unlock_irqrestore(&pctrl->lock, flags); |
f365be09 BA |
420 | } |
421 | ||
422 | return 0; | |
423 | } | |
424 | ||
1f2b2398 | 425 | static const struct pinconf_ops msm_pinconf_ops = { |
38d756af | 426 | .is_generic = true, |
f365be09 BA |
427 | .pin_config_group_get = msm_config_group_get, |
428 | .pin_config_group_set = msm_config_group_set, | |
429 | }; | |
430 | ||
f365be09 BA |
431 | static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset) |
432 | { | |
433 | const struct msm_pingroup *g; | |
fded3f40 | 434 | struct msm_pinctrl *pctrl = gpiochip_get_data(chip); |
f365be09 BA |
435 | unsigned long flags; |
436 | u32 val; | |
437 | ||
f365be09 | 438 | g = &pctrl->soc->groups[offset]; |
f365be09 | 439 | |
47b03ca9 | 440 | raw_spin_lock_irqsave(&pctrl->lock, flags); |
f365be09 | 441 | |
6c736989 | 442 | val = msm_readl_ctl(pctrl, g); |
f365be09 | 443 | val &= ~BIT(g->oe_bit); |
6c736989 | 444 | msm_writel_ctl(val, pctrl, g); |
f365be09 | 445 | |
47b03ca9 | 446 | raw_spin_unlock_irqrestore(&pctrl->lock, flags); |
f365be09 BA |
447 | |
448 | return 0; | |
449 | } | |
450 | ||
451 | static int msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) | |
452 | { | |
453 | const struct msm_pingroup *g; | |
fded3f40 | 454 | struct msm_pinctrl *pctrl = gpiochip_get_data(chip); |
f365be09 BA |
455 | unsigned long flags; |
456 | u32 val; | |
457 | ||
f365be09 | 458 | g = &pctrl->soc->groups[offset]; |
f365be09 | 459 | |
47b03ca9 | 460 | raw_spin_lock_irqsave(&pctrl->lock, flags); |
f365be09 | 461 | |
6c736989 | 462 | val = msm_readl_io(pctrl, g); |
e476e77f AL |
463 | if (value) |
464 | val |= BIT(g->out_bit); | |
465 | else | |
466 | val &= ~BIT(g->out_bit); | |
6c736989 | 467 | msm_writel_io(val, pctrl, g); |
f365be09 | 468 | |
6c736989 | 469 | val = msm_readl_ctl(pctrl, g); |
f365be09 | 470 | val |= BIT(g->oe_bit); |
6c736989 | 471 | msm_writel_ctl(val, pctrl, g); |
f365be09 | 472 | |
47b03ca9 | 473 | raw_spin_unlock_irqrestore(&pctrl->lock, flags); |
f365be09 BA |
474 | |
475 | return 0; | |
476 | } | |
477 | ||
8e515337 TT |
478 | static int msm_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) |
479 | { | |
480 | struct msm_pinctrl *pctrl = gpiochip_get_data(chip); | |
481 | const struct msm_pingroup *g; | |
482 | u32 val; | |
483 | ||
484 | g = &pctrl->soc->groups[offset]; | |
485 | ||
6c736989 | 486 | val = msm_readl_ctl(pctrl, g); |
8e515337 TT |
487 | |
488 | /* 0 = output, 1 = input */ | |
489 | return val & BIT(g->oe_bit) ? 0 : 1; | |
490 | } | |
491 | ||
f365be09 BA |
492 | static int msm_gpio_get(struct gpio_chip *chip, unsigned offset) |
493 | { | |
494 | const struct msm_pingroup *g; | |
fded3f40 | 495 | struct msm_pinctrl *pctrl = gpiochip_get_data(chip); |
f365be09 BA |
496 | u32 val; |
497 | ||
f365be09 BA |
498 | g = &pctrl->soc->groups[offset]; |
499 | ||
6c736989 | 500 | val = msm_readl_io(pctrl, g); |
f365be09 BA |
501 | return !!(val & BIT(g->in_bit)); |
502 | } | |
503 | ||
504 | static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |
505 | { | |
506 | const struct msm_pingroup *g; | |
fded3f40 | 507 | struct msm_pinctrl *pctrl = gpiochip_get_data(chip); |
f365be09 BA |
508 | unsigned long flags; |
509 | u32 val; | |
510 | ||
f365be09 BA |
511 | g = &pctrl->soc->groups[offset]; |
512 | ||
47b03ca9 | 513 | raw_spin_lock_irqsave(&pctrl->lock, flags); |
f365be09 | 514 | |
6c736989 | 515 | val = msm_readl_io(pctrl, g); |
e476e77f AL |
516 | if (value) |
517 | val |= BIT(g->out_bit); | |
518 | else | |
519 | val &= ~BIT(g->out_bit); | |
6c736989 | 520 | msm_writel_io(val, pctrl, g); |
f365be09 | 521 | |
47b03ca9 | 522 | raw_spin_unlock_irqrestore(&pctrl->lock, flags); |
f365be09 BA |
523 | } |
524 | ||
f365be09 BA |
525 | #ifdef CONFIG_DEBUG_FS |
526 | #include <linux/seq_file.h> | |
527 | ||
528 | static void msm_gpio_dbg_show_one(struct seq_file *s, | |
529 | struct pinctrl_dev *pctldev, | |
530 | struct gpio_chip *chip, | |
531 | unsigned offset, | |
532 | unsigned gpio) | |
533 | { | |
534 | const struct msm_pingroup *g; | |
fded3f40 | 535 | struct msm_pinctrl *pctrl = gpiochip_get_data(chip); |
f365be09 BA |
536 | unsigned func; |
537 | int is_out; | |
538 | int drive; | |
539 | int pull; | |
59a18c24 SB |
540 | int val; |
541 | u32 ctl_reg, io_reg; | |
f365be09 | 542 | |
53e73a28 | 543 | static const char * const pulls_keeper[] = { |
f365be09 BA |
544 | "no pull", |
545 | "pull down", | |
546 | "keeper", | |
547 | "pull up" | |
548 | }; | |
549 | ||
53e73a28 CP |
550 | static const char * const pulls_no_keeper[] = { |
551 | "no pull", | |
552 | "pull down", | |
553 | "pull up", | |
554 | }; | |
555 | ||
691bf5d5 SB |
556 | if (!gpiochip_line_is_valid(chip, offset)) |
557 | return; | |
558 | ||
f365be09 | 559 | g = &pctrl->soc->groups[offset]; |
6c736989 BA |
560 | ctl_reg = msm_readl_ctl(pctrl, g); |
561 | io_reg = msm_readl_io(pctrl, g); | |
f365be09 BA |
562 | |
563 | is_out = !!(ctl_reg & BIT(g->oe_bit)); | |
564 | func = (ctl_reg >> g->mux_bit) & 7; | |
565 | drive = (ctl_reg >> g->drv_bit) & 7; | |
566 | pull = (ctl_reg >> g->pull_bit) & 3; | |
567 | ||
59a18c24 SB |
568 | if (is_out) |
569 | val = !!(io_reg & BIT(g->out_bit)); | |
570 | else | |
571 | val = !!(io_reg & BIT(g->in_bit)); | |
572 | ||
573 | seq_printf(s, " %-8s: %-3s", g->name, is_out ? "out" : "in"); | |
574 | seq_printf(s, " %-4s func%d", val ? "high" : "low", func); | |
7cc34e2e | 575 | seq_printf(s, " %dmA", msm_regval_to_drive(drive)); |
53e73a28 CP |
576 | if (pctrl->soc->pull_no_keeper) |
577 | seq_printf(s, " %s", pulls_no_keeper[pull]); | |
578 | else | |
579 | seq_printf(s, " %s", pulls_keeper[pull]); | |
691bf5d5 | 580 | seq_puts(s, "\n"); |
f365be09 BA |
581 | } |
582 | ||
583 | static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |
584 | { | |
585 | unsigned gpio = chip->base; | |
586 | unsigned i; | |
587 | ||
691bf5d5 | 588 | for (i = 0; i < chip->ngpio; i++, gpio++) |
f365be09 | 589 | msm_gpio_dbg_show_one(s, NULL, chip, i, gpio); |
f365be09 BA |
590 | } |
591 | ||
592 | #else | |
593 | #define msm_gpio_dbg_show NULL | |
594 | #endif | |
595 | ||
c9fc5aff LW |
596 | static int msm_gpio_init_valid_mask(struct gpio_chip *gc, |
597 | unsigned long *valid_mask, | |
598 | unsigned int ngpios) | |
6f0ec09a | 599 | { |
c9fc5aff | 600 | struct msm_pinctrl *pctrl = gpiochip_get_data(gc); |
6f0ec09a RRD |
601 | int ret; |
602 | unsigned int len, i; | |
4c0efbfb | 603 | const int *reserved = pctrl->soc->reserved_gpios; |
6f0ec09a RRD |
604 | u16 *tmp; |
605 | ||
4c0efbfb LJ |
606 | /* Driver provided reserved list overrides DT and ACPI */ |
607 | if (reserved) { | |
c9fc5aff | 608 | bitmap_fill(valid_mask, ngpios); |
4c0efbfb | 609 | for (i = 0; reserved[i] >= 0; i++) { |
c9fc5aff | 610 | if (i >= ngpios || reserved[i] >= ngpios) { |
4c0efbfb LJ |
611 | dev_err(pctrl->dev, "invalid list of reserved GPIOs\n"); |
612 | return -EINVAL; | |
613 | } | |
c9fc5aff | 614 | clear_bit(reserved[i], valid_mask); |
4c0efbfb LJ |
615 | } |
616 | ||
617 | return 0; | |
618 | } | |
619 | ||
6f0ec09a RRD |
620 | /* The number of GPIOs in the ACPI tables */ |
621 | len = ret = device_property_read_u16_array(pctrl->dev, "gpios", NULL, | |
622 | 0); | |
623 | if (ret < 0) | |
624 | return 0; | |
625 | ||
c9fc5aff | 626 | if (ret > ngpios) |
6f0ec09a RRD |
627 | return -EINVAL; |
628 | ||
629 | tmp = kmalloc_array(len, sizeof(*tmp), GFP_KERNEL); | |
630 | if (!tmp) | |
631 | return -ENOMEM; | |
632 | ||
633 | ret = device_property_read_u16_array(pctrl->dev, "gpios", tmp, len); | |
634 | if (ret < 0) { | |
635 | dev_err(pctrl->dev, "could not read list of GPIOs\n"); | |
636 | goto out; | |
637 | } | |
638 | ||
c9fc5aff | 639 | bitmap_zero(valid_mask, ngpios); |
6f0ec09a | 640 | for (i = 0; i < len; i++) |
c9fc5aff | 641 | set_bit(tmp[i], valid_mask); |
6f0ec09a RRD |
642 | |
643 | out: | |
644 | kfree(tmp); | |
645 | return ret; | |
646 | } | |
647 | ||
12cb90ba | 648 | static const struct gpio_chip msm_gpio_template = { |
f365be09 BA |
649 | .direction_input = msm_gpio_direction_input, |
650 | .direction_output = msm_gpio_direction_output, | |
8e515337 | 651 | .get_direction = msm_gpio_get_direction, |
f365be09 BA |
652 | .get = msm_gpio_get, |
653 | .set = msm_gpio_set, | |
98c85d58 JG |
654 | .request = gpiochip_generic_request, |
655 | .free = gpiochip_generic_free, | |
f365be09 BA |
656 | .dbg_show = msm_gpio_dbg_show, |
657 | }; | |
658 | ||
659 | /* For dual-edge interrupts in software, since some hardware has no | |
660 | * such support: | |
661 | * | |
662 | * At appropriate moments, this function may be called to flip the polarity | |
663 | * settings of both-edge irq lines to try and catch the next edge. | |
664 | * | |
665 | * The attempt is considered successful if: | |
666 | * - the status bit goes high, indicating that an edge was caught, or | |
667 | * - the input value of the gpio doesn't change during the attempt. | |
668 | * If the value changes twice during the process, that would cause the first | |
669 | * test to fail but would force the second, as two opposite | |
670 | * transitions would cause a detection no matter the polarity setting. | |
671 | * | |
672 | * The do-loop tries to sledge-hammer closed the timing hole between | |
673 | * the initial value-read and the polarity-write - if the line value changes | |
674 | * during that window, an interrupt is lost, the new polarity setting is | |
675 | * incorrect, and the first success test will fail, causing a retry. | |
676 | * | |
677 | * Algorithm comes from Google's msmgpio driver. | |
678 | */ | |
679 | static void msm_gpio_update_dual_edge_pos(struct msm_pinctrl *pctrl, | |
680 | const struct msm_pingroup *g, | |
681 | struct irq_data *d) | |
682 | { | |
683 | int loop_limit = 100; | |
684 | unsigned val, val2, intstat; | |
685 | unsigned pol; | |
686 | ||
687 | do { | |
6c736989 | 688 | val = msm_readl_io(pctrl, g) & BIT(g->in_bit); |
f365be09 | 689 | |
6c736989 | 690 | pol = msm_readl_intr_cfg(pctrl, g); |
f365be09 | 691 | pol ^= BIT(g->intr_polarity_bit); |
6c736989 | 692 | msm_writel_intr_cfg(val, pctrl, g); |
f365be09 | 693 | |
6c736989 BA |
694 | val2 = msm_readl_io(pctrl, g) & BIT(g->in_bit); |
695 | intstat = msm_readl_intr_status(pctrl, g); | |
f365be09 BA |
696 | if (intstat || (val == val2)) |
697 | return; | |
698 | } while (loop_limit-- > 0); | |
699 | dev_err(pctrl->dev, "dual-edge irq failed to stabilize, %#08x != %#08x\n", | |
700 | val, val2); | |
701 | } | |
702 | ||
703 | static void msm_gpio_irq_mask(struct irq_data *d) | |
704 | { | |
cdcb0ab6 | 705 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
fded3f40 | 706 | struct msm_pinctrl *pctrl = gpiochip_get_data(gc); |
f365be09 | 707 | const struct msm_pingroup *g; |
f365be09 BA |
708 | unsigned long flags; |
709 | u32 val; | |
710 | ||
f365be09 BA |
711 | g = &pctrl->soc->groups[d->hwirq]; |
712 | ||
47b03ca9 | 713 | raw_spin_lock_irqsave(&pctrl->lock, flags); |
f365be09 | 714 | |
6c736989 | 715 | val = msm_readl_intr_cfg(pctrl, g); |
b55326dc SB |
716 | /* |
717 | * There are two bits that control interrupt forwarding to the CPU. The | |
718 | * RAW_STATUS_EN bit causes the level or edge sensed on the line to be | |
719 | * latched into the interrupt status register when the hardware detects | |
720 | * an irq that it's configured for (either edge for edge type or level | |
721 | * for level type irq). The 'non-raw' status enable bit causes the | |
722 | * hardware to assert the summary interrupt to the CPU if the latched | |
723 | * status bit is set. There's a bug though, the edge detection logic | |
724 | * seems to have a problem where toggling the RAW_STATUS_EN bit may | |
725 | * cause the status bit to latch spuriously when there isn't any edge | |
726 | * so we can't touch that bit for edge type irqs and we have to keep | |
727 | * the bit set anyway so that edges are latched while the line is masked. | |
728 | * | |
729 | * To make matters more complicated, leaving the RAW_STATUS_EN bit | |
730 | * enabled all the time causes level interrupts to re-latch into the | |
731 | * status register because the level is still present on the line after | |
732 | * we ack it. We clear the raw status enable bit during mask here and | |
733 | * set the bit on unmask so the interrupt can't latch into the hardware | |
734 | * while it's masked. | |
735 | */ | |
736 | if (irqd_get_trigger_type(d) & IRQ_TYPE_LEVEL_MASK) | |
737 | val &= ~BIT(g->intr_raw_status_bit); | |
738 | ||
f365be09 | 739 | val &= ~BIT(g->intr_enable_bit); |
6c736989 | 740 | msm_writel_intr_cfg(val, pctrl, g); |
f365be09 BA |
741 | |
742 | clear_bit(d->hwirq, pctrl->enabled_irqs); | |
743 | ||
47b03ca9 | 744 | raw_spin_unlock_irqrestore(&pctrl->lock, flags); |
f365be09 BA |
745 | } |
746 | ||
4b7618fd | 747 | static void msm_gpio_irq_clear_unmask(struct irq_data *d, bool status_clear) |
f365be09 | 748 | { |
cdcb0ab6 | 749 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
fded3f40 | 750 | struct msm_pinctrl *pctrl = gpiochip_get_data(gc); |
f365be09 | 751 | const struct msm_pingroup *g; |
f365be09 BA |
752 | unsigned long flags; |
753 | u32 val; | |
754 | ||
f365be09 BA |
755 | g = &pctrl->soc->groups[d->hwirq]; |
756 | ||
47b03ca9 | 757 | raw_spin_lock_irqsave(&pctrl->lock, flags); |
f365be09 | 758 | |
4b7618fd SR |
759 | if (status_clear) { |
760 | /* | |
761 | * clear the interrupt status bit before unmask to avoid | |
762 | * any erroneous interrupts that would have got latched | |
763 | * when the interrupt is not in use. | |
764 | */ | |
765 | val = msm_readl_intr_status(pctrl, g); | |
766 | val &= ~BIT(g->intr_status_bit); | |
767 | msm_writel_intr_status(val, pctrl, g); | |
768 | } | |
769 | ||
6c736989 | 770 | val = msm_readl_intr_cfg(pctrl, g); |
b55326dc | 771 | val |= BIT(g->intr_raw_status_bit); |
f365be09 | 772 | val |= BIT(g->intr_enable_bit); |
6c736989 | 773 | msm_writel_intr_cfg(val, pctrl, g); |
f365be09 BA |
774 | |
775 | set_bit(d->hwirq, pctrl->enabled_irqs); | |
776 | ||
47b03ca9 | 777 | raw_spin_unlock_irqrestore(&pctrl->lock, flags); |
f365be09 BA |
778 | } |
779 | ||
4b7618fd SR |
780 | static void msm_gpio_irq_enable(struct irq_data *d) |
781 | { | |
782 | ||
783 | msm_gpio_irq_clear_unmask(d, true); | |
784 | } | |
785 | ||
786 | static void msm_gpio_irq_unmask(struct irq_data *d) | |
787 | { | |
788 | msm_gpio_irq_clear_unmask(d, false); | |
789 | } | |
790 | ||
f365be09 BA |
791 | static void msm_gpio_irq_ack(struct irq_data *d) |
792 | { | |
cdcb0ab6 | 793 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
fded3f40 | 794 | struct msm_pinctrl *pctrl = gpiochip_get_data(gc); |
f365be09 | 795 | const struct msm_pingroup *g; |
f365be09 BA |
796 | unsigned long flags; |
797 | u32 val; | |
798 | ||
f365be09 BA |
799 | g = &pctrl->soc->groups[d->hwirq]; |
800 | ||
47b03ca9 | 801 | raw_spin_lock_irqsave(&pctrl->lock, flags); |
f365be09 | 802 | |
6c736989 | 803 | val = msm_readl_intr_status(pctrl, g); |
48f15e94 BA |
804 | if (g->intr_ack_high) |
805 | val |= BIT(g->intr_status_bit); | |
806 | else | |
807 | val &= ~BIT(g->intr_status_bit); | |
6c736989 | 808 | msm_writel_intr_status(val, pctrl, g); |
f365be09 BA |
809 | |
810 | if (test_bit(d->hwirq, pctrl->dual_edge_irqs)) | |
811 | msm_gpio_update_dual_edge_pos(pctrl, g, d); | |
812 | ||
47b03ca9 | 813 | raw_spin_unlock_irqrestore(&pctrl->lock, flags); |
f365be09 BA |
814 | } |
815 | ||
f365be09 BA |
816 | static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) |
817 | { | |
cdcb0ab6 | 818 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
fded3f40 | 819 | struct msm_pinctrl *pctrl = gpiochip_get_data(gc); |
f365be09 | 820 | const struct msm_pingroup *g; |
f365be09 BA |
821 | unsigned long flags; |
822 | u32 val; | |
823 | ||
f365be09 BA |
824 | g = &pctrl->soc->groups[d->hwirq]; |
825 | ||
47b03ca9 | 826 | raw_spin_lock_irqsave(&pctrl->lock, flags); |
f365be09 BA |
827 | |
828 | /* | |
829 | * For hw without possibility of detecting both edges | |
830 | */ | |
831 | if (g->intr_detection_width == 1 && type == IRQ_TYPE_EDGE_BOTH) | |
832 | set_bit(d->hwirq, pctrl->dual_edge_irqs); | |
833 | else | |
834 | clear_bit(d->hwirq, pctrl->dual_edge_irqs); | |
835 | ||
836 | /* Route interrupts to application cpu */ | |
6c736989 | 837 | val = msm_readl_intr_target(pctrl, g); |
f365be09 | 838 | val &= ~(7 << g->intr_target_bit); |
f712c554 | 839 | val |= g->intr_target_kpss_val << g->intr_target_bit; |
6c736989 | 840 | msm_writel_intr_target(val, pctrl, g); |
f365be09 BA |
841 | |
842 | /* Update configuration for gpio. | |
843 | * RAW_STATUS_EN is left on for all gpio irqs. Due to the | |
844 | * internal circuitry of TLMM, toggling the RAW_STATUS | |
845 | * could cause the INTR_STATUS to be set for EDGE interrupts. | |
846 | */ | |
6c736989 | 847 | val = msm_readl_intr_cfg(pctrl, g); |
f365be09 BA |
848 | val |= BIT(g->intr_raw_status_bit); |
849 | if (g->intr_detection_width == 2) { | |
850 | val &= ~(3 << g->intr_detection_bit); | |
851 | val &= ~(1 << g->intr_polarity_bit); | |
852 | switch (type) { | |
853 | case IRQ_TYPE_EDGE_RISING: | |
854 | val |= 1 << g->intr_detection_bit; | |
855 | val |= BIT(g->intr_polarity_bit); | |
856 | break; | |
857 | case IRQ_TYPE_EDGE_FALLING: | |
858 | val |= 2 << g->intr_detection_bit; | |
859 | val |= BIT(g->intr_polarity_bit); | |
860 | break; | |
861 | case IRQ_TYPE_EDGE_BOTH: | |
862 | val |= 3 << g->intr_detection_bit; | |
863 | val |= BIT(g->intr_polarity_bit); | |
864 | break; | |
865 | case IRQ_TYPE_LEVEL_LOW: | |
866 | break; | |
867 | case IRQ_TYPE_LEVEL_HIGH: | |
868 | val |= BIT(g->intr_polarity_bit); | |
869 | break; | |
870 | } | |
871 | } else if (g->intr_detection_width == 1) { | |
872 | val &= ~(1 << g->intr_detection_bit); | |
873 | val &= ~(1 << g->intr_polarity_bit); | |
874 | switch (type) { | |
875 | case IRQ_TYPE_EDGE_RISING: | |
876 | val |= BIT(g->intr_detection_bit); | |
877 | val |= BIT(g->intr_polarity_bit); | |
878 | break; | |
879 | case IRQ_TYPE_EDGE_FALLING: | |
880 | val |= BIT(g->intr_detection_bit); | |
881 | break; | |
882 | case IRQ_TYPE_EDGE_BOTH: | |
883 | val |= BIT(g->intr_detection_bit); | |
48f15e94 | 884 | val |= BIT(g->intr_polarity_bit); |
f365be09 BA |
885 | break; |
886 | case IRQ_TYPE_LEVEL_LOW: | |
887 | break; | |
888 | case IRQ_TYPE_LEVEL_HIGH: | |
889 | val |= BIT(g->intr_polarity_bit); | |
890 | break; | |
891 | } | |
892 | } else { | |
893 | BUG(); | |
894 | } | |
6c736989 | 895 | msm_writel_intr_cfg(val, pctrl, g); |
f365be09 BA |
896 | |
897 | if (test_bit(d->hwirq, pctrl->dual_edge_irqs)) | |
898 | msm_gpio_update_dual_edge_pos(pctrl, g, d); | |
899 | ||
47b03ca9 | 900 | raw_spin_unlock_irqrestore(&pctrl->lock, flags); |
f365be09 BA |
901 | |
902 | if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) | |
34c0ad84 | 903 | irq_set_handler_locked(d, handle_level_irq); |
f365be09 | 904 | else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) |
34c0ad84 | 905 | irq_set_handler_locked(d, handle_edge_irq); |
f365be09 BA |
906 | |
907 | return 0; | |
908 | } | |
909 | ||
910 | static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on) | |
911 | { | |
cdcb0ab6 | 912 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); |
fded3f40 | 913 | struct msm_pinctrl *pctrl = gpiochip_get_data(gc); |
f365be09 | 914 | unsigned long flags; |
f365be09 | 915 | |
47b03ca9 | 916 | raw_spin_lock_irqsave(&pctrl->lock, flags); |
f365be09 | 917 | |
6aced33f | 918 | irq_set_irq_wake(pctrl->irq, on); |
f365be09 | 919 | |
47b03ca9 | 920 | raw_spin_unlock_irqrestore(&pctrl->lock, flags); |
f365be09 BA |
921 | |
922 | return 0; | |
923 | } | |
924 | ||
fe273121 SB |
925 | static int msm_gpio_irq_reqres(struct irq_data *d) |
926 | { | |
927 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | |
928 | struct msm_pinctrl *pctrl = gpiochip_get_data(gc); | |
929 | int ret; | |
930 | ||
931 | if (!try_module_get(gc->owner)) | |
932 | return -ENODEV; | |
933 | ||
934 | ret = msm_pinmux_request_gpio(pctrl->pctrl, NULL, d->hwirq); | |
935 | if (ret) | |
936 | goto out; | |
937 | msm_gpio_direction_input(gc, d->hwirq); | |
938 | ||
939 | if (gpiochip_lock_as_irq(gc, d->hwirq)) { | |
940 | dev_err(gc->parent, | |
941 | "unable to lock HW IRQ %lu for IRQ\n", | |
942 | d->hwirq); | |
943 | ret = -EINVAL; | |
944 | goto out; | |
945 | } | |
946 | return 0; | |
947 | out: | |
948 | module_put(gc->owner); | |
949 | return ret; | |
950 | } | |
951 | ||
952 | static void msm_gpio_irq_relres(struct irq_data *d) | |
953 | { | |
954 | struct gpio_chip *gc = irq_data_get_irq_chip_data(d); | |
955 | ||
956 | gpiochip_unlock_as_irq(gc, d->hwirq); | |
957 | module_put(gc->owner); | |
958 | } | |
959 | ||
bd0b9ac4 | 960 | static void msm_gpio_irq_handler(struct irq_desc *desc) |
f365be09 | 961 | { |
cdcb0ab6 | 962 | struct gpio_chip *gc = irq_desc_get_handler_data(desc); |
f365be09 | 963 | const struct msm_pingroup *g; |
fded3f40 | 964 | struct msm_pinctrl *pctrl = gpiochip_get_data(gc); |
5663bb27 | 965 | struct irq_chip *chip = irq_desc_get_chip(desc); |
f365be09 BA |
966 | int irq_pin; |
967 | int handled = 0; | |
968 | u32 val; | |
969 | int i; | |
970 | ||
971 | chained_irq_enter(chip, desc); | |
972 | ||
973 | /* | |
1f2b2398 | 974 | * Each pin has it's own IRQ status register, so use |
f365be09 BA |
975 | * enabled_irq bitmap to limit the number of reads. |
976 | */ | |
977 | for_each_set_bit(i, pctrl->enabled_irqs, pctrl->chip.ngpio) { | |
978 | g = &pctrl->soc->groups[i]; | |
6c736989 | 979 | val = msm_readl_intr_status(pctrl, g); |
f365be09 | 980 | if (val & BIT(g->intr_status_bit)) { |
f0fbe7bc | 981 | irq_pin = irq_find_mapping(gc->irq.domain, i); |
f365be09 BA |
982 | generic_handle_irq(irq_pin); |
983 | handled++; | |
984 | } | |
985 | } | |
986 | ||
1f2b2398 | 987 | /* No interrupts were flagged */ |
f365be09 | 988 | if (handled == 0) |
bd0b9ac4 | 989 | handle_bad_irq(desc); |
f365be09 BA |
990 | |
991 | chained_irq_exit(chip, desc); | |
992 | } | |
993 | ||
691bf5d5 SB |
994 | static bool msm_gpio_needs_valid_mask(struct msm_pinctrl *pctrl) |
995 | { | |
4c0efbfb LJ |
996 | if (pctrl->soc->reserved_gpios) |
997 | return true; | |
998 | ||
691bf5d5 SB |
999 | return device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0) > 0; |
1000 | } | |
1001 | ||
f365be09 BA |
1002 | static int msm_gpio_init(struct msm_pinctrl *pctrl) |
1003 | { | |
1004 | struct gpio_chip *chip; | |
f365be09 | 1005 | int ret; |
dcd278b8 SB |
1006 | unsigned ngpio = pctrl->soc->ngpios; |
1007 | ||
1008 | if (WARN_ON(ngpio > MAX_NR_GPIO)) | |
1009 | return -EINVAL; | |
f365be09 BA |
1010 | |
1011 | chip = &pctrl->chip; | |
a7aa75a2 | 1012 | chip->base = -1; |
dcd278b8 | 1013 | chip->ngpio = ngpio; |
f365be09 | 1014 | chip->label = dev_name(pctrl->dev); |
58383c78 | 1015 | chip->parent = pctrl->dev; |
f365be09 BA |
1016 | chip->owner = THIS_MODULE; |
1017 | chip->of_node = pctrl->dev->of_node; | |
eb1e8bd6 LW |
1018 | if (msm_gpio_needs_valid_mask(pctrl)) |
1019 | chip->init_valid_mask = msm_gpio_init_valid_mask; | |
f365be09 | 1020 | |
f265e8b9 | 1021 | pctrl->irq_chip.name = "msmgpio"; |
4b7618fd | 1022 | pctrl->irq_chip.irq_enable = msm_gpio_irq_enable; |
f265e8b9 TT |
1023 | pctrl->irq_chip.irq_mask = msm_gpio_irq_mask; |
1024 | pctrl->irq_chip.irq_unmask = msm_gpio_irq_unmask; | |
1025 | pctrl->irq_chip.irq_ack = msm_gpio_irq_ack; | |
1026 | pctrl->irq_chip.irq_set_type = msm_gpio_irq_set_type; | |
1027 | pctrl->irq_chip.irq_set_wake = msm_gpio_irq_set_wake; | |
fe273121 SB |
1028 | pctrl->irq_chip.irq_request_resources = msm_gpio_irq_reqres; |
1029 | pctrl->irq_chip.irq_release_resources = msm_gpio_irq_relres; | |
f265e8b9 | 1030 | |
fded3f40 | 1031 | ret = gpiochip_add_data(&pctrl->chip, pctrl); |
f365be09 BA |
1032 | if (ret) { |
1033 | dev_err(pctrl->dev, "Failed register gpiochip\n"); | |
1034 | return ret; | |
1035 | } | |
1036 | ||
a86caa9b CL |
1037 | /* |
1038 | * For DeviceTree-supported systems, the gpio core checks the | |
1039 | * pinctrl's device node for the "gpio-ranges" property. | |
1040 | * If it is present, it takes care of adding the pin ranges | |
1041 | * for the driver. In this case the driver can skip ahead. | |
1042 | * | |
1043 | * In order to remain compatible with older, existing DeviceTree | |
1044 | * files which don't set the "gpio-ranges" property or systems that | |
1045 | * utilize ACPI the driver has to call gpiochip_add_pin_range(). | |
1046 | */ | |
1047 | if (!of_property_read_bool(pctrl->dev->of_node, "gpio-ranges")) { | |
1048 | ret = gpiochip_add_pin_range(&pctrl->chip, | |
1049 | dev_name(pctrl->dev), 0, 0, chip->ngpio); | |
1050 | if (ret) { | |
1051 | dev_err(pctrl->dev, "Failed to add pin range\n"); | |
1052 | gpiochip_remove(&pctrl->chip); | |
1053 | return ret; | |
1054 | } | |
f365be09 BA |
1055 | } |
1056 | ||
cdcb0ab6 | 1057 | ret = gpiochip_irqchip_add(chip, |
f265e8b9 | 1058 | &pctrl->irq_chip, |
cdcb0ab6 LW |
1059 | 0, |
1060 | handle_edge_irq, | |
1061 | IRQ_TYPE_NONE); | |
1062 | if (ret) { | |
1063 | dev_err(pctrl->dev, "Failed to add irqchip to gpiochip\n"); | |
c6e927a2 | 1064 | gpiochip_remove(&pctrl->chip); |
f365be09 BA |
1065 | return -ENOSYS; |
1066 | } | |
1067 | ||
f265e8b9 | 1068 | gpiochip_set_chained_irqchip(chip, &pctrl->irq_chip, pctrl->irq, |
cdcb0ab6 | 1069 | msm_gpio_irq_handler); |
f365be09 BA |
1070 | |
1071 | return 0; | |
1072 | } | |
1073 | ||
cf1fc187 JC |
1074 | static int msm_ps_hold_restart(struct notifier_block *nb, unsigned long action, |
1075 | void *data) | |
32745581 | 1076 | { |
cf1fc187 JC |
1077 | struct msm_pinctrl *pctrl = container_of(nb, struct msm_pinctrl, restart_nb); |
1078 | ||
a46d5e98 | 1079 | writel(0, pctrl->regs[0] + PS_HOLD_OFFSET); |
cf1fc187 JC |
1080 | mdelay(1000); |
1081 | return NOTIFY_DONE; | |
32745581 PG |
1082 | } |
1083 | ||
ad644987 SB |
1084 | static struct msm_pinctrl *poweroff_pctrl; |
1085 | ||
1086 | static void msm_ps_hold_poweroff(void) | |
1087 | { | |
1088 | msm_ps_hold_restart(&poweroff_pctrl->restart_nb, 0, NULL); | |
1089 | } | |
1090 | ||
32745581 PG |
1091 | static void msm_pinctrl_setup_pm_reset(struct msm_pinctrl *pctrl) |
1092 | { | |
bcd53f85 | 1093 | int i; |
32745581 PG |
1094 | const struct msm_function *func = pctrl->soc->functions; |
1095 | ||
bcd53f85 | 1096 | for (i = 0; i < pctrl->soc->nfunctions; i++) |
32745581 | 1097 | if (!strcmp(func[i].name, "ps_hold")) { |
cf1fc187 JC |
1098 | pctrl->restart_nb.notifier_call = msm_ps_hold_restart; |
1099 | pctrl->restart_nb.priority = 128; | |
1100 | if (register_restart_handler(&pctrl->restart_nb)) | |
1101 | dev_err(pctrl->dev, | |
1102 | "failed to setup restart handler.\n"); | |
ad644987 SB |
1103 | poweroff_pctrl = pctrl; |
1104 | pm_power_off = msm_ps_hold_poweroff; | |
cf1fc187 | 1105 | break; |
32745581 PG |
1106 | } |
1107 | } | |
32745581 | 1108 | |
d1040ea0 | 1109 | static __maybe_unused int msm_pinctrl_suspend(struct device *dev) |
977d057a EG |
1110 | { |
1111 | struct msm_pinctrl *pctrl = dev_get_drvdata(dev); | |
1112 | ||
1113 | return pinctrl_force_sleep(pctrl->pctrl); | |
1114 | } | |
1115 | ||
d1040ea0 | 1116 | static __maybe_unused int msm_pinctrl_resume(struct device *dev) |
977d057a EG |
1117 | { |
1118 | struct msm_pinctrl *pctrl = dev_get_drvdata(dev); | |
1119 | ||
1120 | return pinctrl_force_default(pctrl->pctrl); | |
1121 | } | |
1122 | ||
1123 | SIMPLE_DEV_PM_OPS(msm_pinctrl_dev_pm_ops, msm_pinctrl_suspend, | |
1124 | msm_pinctrl_resume); | |
1125 | ||
1126 | EXPORT_SYMBOL(msm_pinctrl_dev_pm_ops); | |
1127 | ||
f365be09 BA |
1128 | int msm_pinctrl_probe(struct platform_device *pdev, |
1129 | const struct msm_pinctrl_soc_data *soc_data) | |
1130 | { | |
1131 | struct msm_pinctrl *pctrl; | |
1132 | struct resource *res; | |
1133 | int ret; | |
a46d5e98 | 1134 | int i; |
f365be09 BA |
1135 | |
1136 | pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL); | |
203f4b06 | 1137 | if (!pctrl) |
f365be09 | 1138 | return -ENOMEM; |
203f4b06 | 1139 | |
f365be09 BA |
1140 | pctrl->dev = &pdev->dev; |
1141 | pctrl->soc = soc_data; | |
1142 | pctrl->chip = msm_gpio_template; | |
1143 | ||
47b03ca9 | 1144 | raw_spin_lock_init(&pctrl->lock); |
f365be09 | 1145 | |
a46d5e98 BA |
1146 | if (soc_data->tiles) { |
1147 | for (i = 0; i < soc_data->ntiles; i++) { | |
1148 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | |
1149 | soc_data->tiles[i]); | |
1150 | pctrl->regs[i] = devm_ioremap_resource(&pdev->dev, res); | |
1151 | if (IS_ERR(pctrl->regs[i])) | |
1152 | return PTR_ERR(pctrl->regs[i]); | |
1153 | } | |
1154 | } else { | |
1155 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
1156 | pctrl->regs[0] = devm_ioremap_resource(&pdev->dev, res); | |
1157 | if (IS_ERR(pctrl->regs[0])) | |
1158 | return PTR_ERR(pctrl->regs[0]); | |
1159 | } | |
f365be09 | 1160 | |
32745581 PG |
1161 | msm_pinctrl_setup_pm_reset(pctrl); |
1162 | ||
f393e489 | 1163 | pctrl->irq = platform_get_irq(pdev, 0); |
f365be09 BA |
1164 | if (pctrl->irq < 0) { |
1165 | dev_err(&pdev->dev, "No interrupt defined for msmgpio\n"); | |
1166 | return pctrl->irq; | |
1167 | } | |
1168 | ||
f265e8b9 TT |
1169 | pctrl->desc.owner = THIS_MODULE; |
1170 | pctrl->desc.pctlops = &msm_pinctrl_ops; | |
1171 | pctrl->desc.pmxops = &msm_pinmux_ops; | |
1172 | pctrl->desc.confops = &msm_pinconf_ops; | |
1173 | pctrl->desc.name = dev_name(&pdev->dev); | |
1174 | pctrl->desc.pins = pctrl->soc->pins; | |
1175 | pctrl->desc.npins = pctrl->soc->npins; | |
1176 | ||
1177 | pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl); | |
323de9ef | 1178 | if (IS_ERR(pctrl->pctrl)) { |
f365be09 | 1179 | dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); |
323de9ef | 1180 | return PTR_ERR(pctrl->pctrl); |
f365be09 BA |
1181 | } |
1182 | ||
1183 | ret = msm_gpio_init(pctrl); | |
fe0267f4 | 1184 | if (ret) |
f365be09 | 1185 | return ret; |
f365be09 BA |
1186 | |
1187 | platform_set_drvdata(pdev, pctrl); | |
1188 | ||
1189 | dev_dbg(&pdev->dev, "Probed Qualcomm pinctrl driver\n"); | |
1190 | ||
1191 | return 0; | |
1192 | } | |
1193 | EXPORT_SYMBOL(msm_pinctrl_probe); | |
1194 | ||
1195 | int msm_pinctrl_remove(struct platform_device *pdev) | |
1196 | { | |
1197 | struct msm_pinctrl *pctrl = platform_get_drvdata(pdev); | |
f393e489 | 1198 | |
2fcea6ce | 1199 | gpiochip_remove(&pctrl->chip); |
f365be09 | 1200 | |
cf1fc187 JC |
1201 | unregister_restart_handler(&pctrl->restart_nb); |
1202 | ||
f365be09 BA |
1203 | return 0; |
1204 | } | |
1205 | EXPORT_SYMBOL(msm_pinctrl_remove); | |
1206 |