diff options
author | Tomasz Figa <t.figa@samsung.com> | 2012-10-11 04:11:18 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2012-10-15 03:10:12 -0400 |
commit | a04b07c0fc4d63e3fb9fea84d48a177ac5bd9164 (patch) | |
tree | 38504cfbceac9b3ed6359caded76a626b633fa12 | |
parent | d3a7b9e3a168df881a0ae3bd0d582f44a5d5aca3 (diff) |
pinctrl: samsung: Use per-bank IRQ domain for wake-up interrupts
This patch reworks wake-up interrupt handling in pinctrl-exynos driver,
so each pin bank, which provides wake-up interrupts, has its own IRQ
domain.
Information about whether given pin bank provides wake-up interrupts,
how many and whether they are separate or muxed are parsed from device
tree.
It gives following advantages:
- interrupts can be specified in device tree in a more readable way,
e.g. :
device {
/* ... */
interrupt-parent = <&gpx2>;
interrupts = <4 0>;
/* ... */
};
- the amount and layout of interrupts is not hardcoded in the code
anymore, but defined in SoC-specific structure
- bank and pin of each wake-up interrupt can be easily identified, to
allow operations, such as setting the pin to EINT function, from
irq_set_type() callback
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Reviewed-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Thomas Abraham <thomas.abraham@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r-- | arch/arm/boot/dts/exynos4210-pinctrl.dtsi | 6 | ||||
-rw-r--r-- | arch/arm/boot/dts/exynos4210.dtsi | 8 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-exynos.c | 163 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-exynos.h | 29 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-samsung.h | 6 |
5 files changed, 136 insertions, 76 deletions
diff --git a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi index f207d8d69170..6a4a1a04221c 100644 --- a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi +++ b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi | |||
@@ -445,6 +445,9 @@ | |||
445 | #gpio-cells = <2>; | 445 | #gpio-cells = <2>; |
446 | 446 | ||
447 | interrupt-controller; | 447 | interrupt-controller; |
448 | interrupt-parent = <&gic>; | ||
449 | interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>, | ||
450 | <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>; | ||
448 | #interrupt-cells = <2>; | 451 | #interrupt-cells = <2>; |
449 | }; | 452 | }; |
450 | 453 | ||
@@ -453,6 +456,9 @@ | |||
453 | #gpio-cells = <2>; | 456 | #gpio-cells = <2>; |
454 | 457 | ||
455 | interrupt-controller; | 458 | interrupt-controller; |
459 | interrupt-parent = <&gic>; | ||
460 | interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>, | ||
461 | <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>; | ||
456 | #interrupt-cells = <2>; | 462 | #interrupt-cells = <2>; |
457 | }; | 463 | }; |
458 | 464 | ||
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi index c27aea73abf7..d877dbe7ac0e 100644 --- a/arch/arm/boot/dts/exynos4210.dtsi +++ b/arch/arm/boot/dts/exynos4210.dtsi | |||
@@ -56,13 +56,7 @@ | |||
56 | wakup_eint: wakeup-interrupt-controller { | 56 | wakup_eint: wakeup-interrupt-controller { |
57 | compatible = "samsung,exynos4210-wakeup-eint"; | 57 | compatible = "samsung,exynos4210-wakeup-eint"; |
58 | interrupt-parent = <&gic>; | 58 | interrupt-parent = <&gic>; |
59 | interrupt-controller; | 59 | interrupts = <0 32 0>; |
60 | #interrupt-cells = <2>; | ||
61 | interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>, | ||
62 | <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>, | ||
63 | <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>, | ||
64 | <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>, | ||
65 | <0 32 0>; | ||
66 | }; | 60 | }; |
67 | }; | 61 | }; |
68 | 62 | ||
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index be757b1d4fcd..4bf2fc40aca8 100644 --- a/drivers/pinctrl/pinctrl-exynos.c +++ b/drivers/pinctrl/pinctrl-exynos.c | |||
@@ -218,46 +218,43 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d) | |||
218 | 218 | ||
219 | static void exynos_wkup_irq_unmask(struct irq_data *irqd) | 219 | static void exynos_wkup_irq_unmask(struct irq_data *irqd) |
220 | { | 220 | { |
221 | struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd); | 221 | struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd); |
222 | unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK; | 222 | struct samsung_pinctrl_drv_data *d = b->drvdata; |
223 | unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1); | 223 | unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset; |
224 | unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2); | ||
225 | unsigned long mask; | 224 | unsigned long mask; |
226 | 225 | ||
227 | mask = readl(d->virt_base + reg_mask); | 226 | mask = readl(d->virt_base + reg_mask); |
228 | mask &= ~(1 << pin); | 227 | mask &= ~(1 << irqd->hwirq); |
229 | writel(mask, d->virt_base + reg_mask); | 228 | writel(mask, d->virt_base + reg_mask); |
230 | } | 229 | } |
231 | 230 | ||
232 | static void exynos_wkup_irq_mask(struct irq_data *irqd) | 231 | static void exynos_wkup_irq_mask(struct irq_data *irqd) |
233 | { | 232 | { |
234 | struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd); | 233 | struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd); |
235 | unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK; | 234 | struct samsung_pinctrl_drv_data *d = b->drvdata; |
236 | unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1); | 235 | unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset; |
237 | unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2); | ||
238 | unsigned long mask; | 236 | unsigned long mask; |
239 | 237 | ||
240 | mask = readl(d->virt_base + reg_mask); | 238 | mask = readl(d->virt_base + reg_mask); |
241 | mask |= 1 << pin; | 239 | mask |= 1 << irqd->hwirq; |
242 | writel(mask, d->virt_base + reg_mask); | 240 | writel(mask, d->virt_base + reg_mask); |
243 | } | 241 | } |
244 | 242 | ||
245 | static void exynos_wkup_irq_ack(struct irq_data *irqd) | 243 | static void exynos_wkup_irq_ack(struct irq_data *irqd) |
246 | { | 244 | { |
247 | struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd); | 245 | struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd); |
248 | unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK; | 246 | struct samsung_pinctrl_drv_data *d = b->drvdata; |
249 | unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1); | 247 | unsigned long pend = d->ctrl->weint_pend + b->eint_offset; |
250 | unsigned long pend = d->ctrl->weint_pend + (bank << 2); | ||
251 | 248 | ||
252 | writel(1 << pin, d->virt_base + pend); | 249 | writel(1 << irqd->hwirq, d->virt_base + pend); |
253 | } | 250 | } |
254 | 251 | ||
255 | static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type) | 252 | static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type) |
256 | { | 253 | { |
257 | struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd); | 254 | struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); |
258 | unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK; | 255 | struct samsung_pinctrl_drv_data *d = bank->drvdata; |
259 | unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1); | 256 | unsigned int pin = irqd->hwirq; |
260 | unsigned long reg_con = d->ctrl->weint_con + (bank << 2); | 257 | unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset; |
261 | unsigned long shift = EXYNOS_EINT_CON_LEN * pin; | 258 | unsigned long shift = EXYNOS_EINT_CON_LEN * pin; |
262 | unsigned long con, trig_type; | 259 | unsigned long con, trig_type; |
263 | 260 | ||
@@ -309,6 +306,7 @@ static struct irq_chip exynos_wkup_irq_chip = { | |||
309 | static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc) | 306 | static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc) |
310 | { | 307 | { |
311 | struct exynos_weint_data *eintd = irq_get_handler_data(irq); | 308 | struct exynos_weint_data *eintd = irq_get_handler_data(irq); |
309 | struct samsung_pin_bank *bank = eintd->bank; | ||
312 | struct irq_chip *chip = irq_get_chip(irq); | 310 | struct irq_chip *chip = irq_get_chip(irq); |
313 | int eint_irq; | 311 | int eint_irq; |
314 | 312 | ||
@@ -318,20 +316,20 @@ static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc) | |||
318 | if (chip->irq_ack) | 316 | if (chip->irq_ack) |
319 | chip->irq_ack(&desc->irq_data); | 317 | chip->irq_ack(&desc->irq_data); |
320 | 318 | ||
321 | eint_irq = irq_linear_revmap(eintd->domain, eintd->irq); | 319 | eint_irq = irq_linear_revmap(bank->irq_domain, eintd->irq); |
322 | generic_handle_irq(eint_irq); | 320 | generic_handle_irq(eint_irq); |
323 | chip->irq_unmask(&desc->irq_data); | 321 | chip->irq_unmask(&desc->irq_data); |
324 | chained_irq_exit(chip, desc); | 322 | chained_irq_exit(chip, desc); |
325 | } | 323 | } |
326 | 324 | ||
327 | static inline void exynos_irq_demux_eint(int irq_base, unsigned long pend, | 325 | static inline void exynos_irq_demux_eint(unsigned long pend, |
328 | struct irq_domain *domain) | 326 | struct irq_domain *domain) |
329 | { | 327 | { |
330 | unsigned int irq; | 328 | unsigned int irq; |
331 | 329 | ||
332 | while (pend) { | 330 | while (pend) { |
333 | irq = fls(pend) - 1; | 331 | irq = fls(pend) - 1; |
334 | generic_handle_irq(irq_find_mapping(domain, irq_base + irq)); | 332 | generic_handle_irq(irq_find_mapping(domain, irq)); |
335 | pend &= ~(1 << irq); | 333 | pend &= ~(1 << irq); |
336 | } | 334 | } |
337 | } | 335 | } |
@@ -340,18 +338,22 @@ static inline void exynos_irq_demux_eint(int irq_base, unsigned long pend, | |||
340 | static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc) | 338 | static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc) |
341 | { | 339 | { |
342 | struct irq_chip *chip = irq_get_chip(irq); | 340 | struct irq_chip *chip = irq_get_chip(irq); |
343 | struct exynos_weint_data *eintd = irq_get_handler_data(irq); | 341 | struct exynos_muxed_weint_data *eintd = irq_get_handler_data(irq); |
344 | struct samsung_pinctrl_drv_data *d = eintd->domain->host_data; | 342 | struct samsung_pinctrl_drv_data *d = eintd->banks[0]->drvdata; |
343 | struct samsung_pin_ctrl *ctrl = d->ctrl; | ||
345 | unsigned long pend; | 344 | unsigned long pend; |
346 | unsigned long mask; | 345 | unsigned long mask; |
346 | int i; | ||
347 | 347 | ||
348 | chained_irq_enter(chip, desc); | 348 | chained_irq_enter(chip, desc); |
349 | pend = readl(d->virt_base + d->ctrl->weint_pend + 0x8); | 349 | |
350 | mask = readl(d->virt_base + d->ctrl->weint_mask + 0x8); | 350 | for (i = 0; i < eintd->nr_banks; ++i) { |
351 | exynos_irq_demux_eint(16, pend & ~mask, eintd->domain); | 351 | struct samsung_pin_bank *b = eintd->banks[i]; |
352 | pend = readl(d->virt_base + d->ctrl->weint_pend + 0xC); | 352 | pend = readl(d->virt_base + ctrl->weint_pend + b->eint_offset); |
353 | mask = readl(d->virt_base + d->ctrl->weint_mask + 0xC); | 353 | mask = readl(d->virt_base + ctrl->weint_mask + b->eint_offset); |
354 | exynos_irq_demux_eint(24, pend & ~mask, eintd->domain); | 354 | exynos_irq_demux_eint(pend & ~mask, b->irq_domain); |
355 | } | ||
356 | |||
355 | chained_irq_exit(chip, desc); | 357 | chained_irq_exit(chip, desc); |
356 | } | 358 | } |
357 | 359 | ||
@@ -381,7 +383,11 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) | |||
381 | struct device *dev = d->dev; | 383 | struct device *dev = d->dev; |
382 | struct device_node *wkup_np = NULL; | 384 | struct device_node *wkup_np = NULL; |
383 | struct device_node *np; | 385 | struct device_node *np; |
386 | struct samsung_pin_bank *bank; | ||
384 | struct exynos_weint_data *weint_data; | 387 | struct exynos_weint_data *weint_data; |
388 | struct exynos_muxed_weint_data *muxed_data; | ||
389 | unsigned int muxed_banks = 0; | ||
390 | unsigned int i; | ||
385 | int idx, irq; | 391 | int idx, irq; |
386 | 392 | ||
387 | for_each_child_of_node(dev->of_node, np) { | 393 | for_each_child_of_node(dev->of_node, np) { |
@@ -393,40 +399,74 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) | |||
393 | if (!wkup_np) | 399 | if (!wkup_np) |
394 | return -ENODEV; | 400 | return -ENODEV; |
395 | 401 | ||
396 | d->wkup_irqd = irq_domain_add_linear(wkup_np, d->ctrl->nr_wint, | 402 | bank = d->ctrl->pin_banks; |
397 | &exynos_wkup_irqd_ops, d); | 403 | for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) { |
398 | if (!d->wkup_irqd) { | 404 | if (bank->eint_type != EINT_TYPE_WKUP) |
399 | dev_err(dev, "wakeup irq domain allocation failed\n"); | 405 | continue; |
400 | return -ENXIO; | ||
401 | } | ||
402 | 406 | ||
403 | weint_data = devm_kzalloc(dev, sizeof(*weint_data) * 17, GFP_KERNEL); | 407 | bank->irq_domain = irq_domain_add_linear(bank->of_node, |
404 | if (!weint_data) { | 408 | bank->nr_pins, &exynos_wkup_irqd_ops, bank); |
405 | dev_err(dev, "could not allocate memory for weint_data\n"); | 409 | if (!bank->irq_domain) { |
406 | return -ENOMEM; | 410 | dev_err(dev, "wkup irq domain add failed\n"); |
407 | } | 411 | return -ENXIO; |
412 | } | ||
408 | 413 | ||
409 | irq = irq_of_parse_and_map(wkup_np, 16); | 414 | if (!of_find_property(bank->of_node, "interrupts", NULL)) { |
410 | if (irq) { | 415 | bank->eint_type = EINT_TYPE_WKUP_MUX; |
411 | weint_data[16].domain = d->wkup_irqd; | 416 | ++muxed_banks; |
412 | irq_set_chained_handler(irq, exynos_irq_demux_eint16_31); | 417 | continue; |
413 | irq_set_handler_data(irq, &weint_data[16]); | 418 | } |
414 | } else { | ||
415 | dev_err(dev, "irq number for EINT16-32 not found\n"); | ||
416 | } | ||
417 | 419 | ||
418 | for (idx = 0; idx < 16; idx++) { | 420 | weint_data = devm_kzalloc(dev, bank->nr_pins |
419 | weint_data[idx].domain = d->wkup_irqd; | 421 | * sizeof(*weint_data), GFP_KERNEL); |
420 | weint_data[idx].irq = idx; | 422 | if (!weint_data) { |
423 | dev_err(dev, "could not allocate memory for weint_data\n"); | ||
424 | return -ENOMEM; | ||
425 | } | ||
421 | 426 | ||
422 | irq = irq_of_parse_and_map(wkup_np, idx); | 427 | for (idx = 0; idx < bank->nr_pins; ++idx) { |
423 | if (irq) { | 428 | irq = irq_of_parse_and_map(bank->of_node, idx); |
429 | if (!irq) { | ||
430 | dev_err(dev, "irq number for eint-%s-%d not found\n", | ||
431 | bank->name, idx); | ||
432 | continue; | ||
433 | } | ||
434 | weint_data[idx].irq = idx; | ||
435 | weint_data[idx].bank = bank; | ||
424 | irq_set_handler_data(irq, &weint_data[idx]); | 436 | irq_set_handler_data(irq, &weint_data[idx]); |
425 | irq_set_chained_handler(irq, exynos_irq_eint0_15); | 437 | irq_set_chained_handler(irq, exynos_irq_eint0_15); |
426 | } else { | ||
427 | dev_err(dev, "irq number for eint-%x not found\n", idx); | ||
428 | } | 438 | } |
429 | } | 439 | } |
440 | |||
441 | if (!muxed_banks) | ||
442 | return 0; | ||
443 | |||
444 | irq = irq_of_parse_and_map(wkup_np, 0); | ||
445 | if (!irq) { | ||
446 | dev_err(dev, "irq number for muxed EINTs not found\n"); | ||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | muxed_data = devm_kzalloc(dev, sizeof(*muxed_data) | ||
451 | + muxed_banks*sizeof(struct samsung_pin_bank *), GFP_KERNEL); | ||
452 | if (!muxed_data) { | ||
453 | dev_err(dev, "could not allocate memory for muxed_data\n"); | ||
454 | return -ENOMEM; | ||
455 | } | ||
456 | |||
457 | irq_set_chained_handler(irq, exynos_irq_demux_eint16_31); | ||
458 | irq_set_handler_data(irq, muxed_data); | ||
459 | |||
460 | bank = d->ctrl->pin_banks; | ||
461 | idx = 0; | ||
462 | for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) { | ||
463 | if (bank->eint_type != EINT_TYPE_WKUP_MUX) | ||
464 | continue; | ||
465 | |||
466 | muxed_data->banks[idx++] = bank; | ||
467 | } | ||
468 | muxed_data->nr_banks = muxed_banks; | ||
469 | |||
430 | return 0; | 470 | return 0; |
431 | } | 471 | } |
432 | 472 | ||
@@ -468,10 +508,10 @@ static struct samsung_pin_bank exynos4210_pin_banks1[] = { | |||
468 | EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "gpy4"), | 508 | EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "gpy4"), |
469 | EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "gpy5"), | 509 | EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "gpy5"), |
470 | EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "gpy6"), | 510 | EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "gpy6"), |
471 | EXYNOS_PIN_BANK_EINTN(8, 0xC00, "gpx0"), | 511 | EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00), |
472 | EXYNOS_PIN_BANK_EINTN(8, 0xC20, "gpx1"), | 512 | EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04), |
473 | EXYNOS_PIN_BANK_EINTN(8, 0xC40, "gpx2"), | 513 | EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08), |
474 | EXYNOS_PIN_BANK_EINTN(8, 0xC60, "gpx3"), | 514 | EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c), |
475 | }; | 515 | }; |
476 | 516 | ||
477 | /* pin banks of exynos4210 pin-controller 2 */ | 517 | /* pin banks of exynos4210 pin-controller 2 */ |
@@ -498,7 +538,6 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = { | |||
498 | /* pin-controller instance 1 data */ | 538 | /* pin-controller instance 1 data */ |
499 | .pin_banks = exynos4210_pin_banks1, | 539 | .pin_banks = exynos4210_pin_banks1, |
500 | .nr_banks = ARRAY_SIZE(exynos4210_pin_banks1), | 540 | .nr_banks = ARRAY_SIZE(exynos4210_pin_banks1), |
501 | .nr_wint = 32, | ||
502 | .geint_con = EXYNOS_GPIO_ECON_OFFSET, | 541 | .geint_con = EXYNOS_GPIO_ECON_OFFSET, |
503 | .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, | 542 | .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, |
504 | .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, | 543 | .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, |
diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h index f05efa074658..0a708890d8b4 100644 --- a/drivers/pinctrl/pinctrl-exynos.h +++ b/drivers/pinctrl/pinctrl-exynos.h | |||
@@ -73,13 +73,36 @@ | |||
73 | .name = id \ | 73 | .name = id \ |
74 | } | 74 | } |
75 | 75 | ||
76 | #define EXYNOS_PIN_BANK_EINTW(pins, reg, id, offs) \ | ||
77 | { \ | ||
78 | .pctl_offset = reg, \ | ||
79 | .nr_pins = pins, \ | ||
80 | .func_width = 4, \ | ||
81 | .pud_width = 2, \ | ||
82 | .drv_width = 2, \ | ||
83 | .eint_type = EINT_TYPE_WKUP, \ | ||
84 | .eint_offset = offs, \ | ||
85 | .name = id \ | ||
86 | } | ||
87 | |||
76 | /** | 88 | /** |
77 | * struct exynos_weint_data: irq specific data for all the wakeup interrupts | 89 | * struct exynos_weint_data: irq specific data for all the wakeup interrupts |
78 | * generated by the external wakeup interrupt controller. | 90 | * generated by the external wakeup interrupt controller. |
79 | * @domain: irq domain representing the external wakeup interrupts | ||
80 | * @irq: interrupt number within the domain. | 91 | * @irq: interrupt number within the domain. |
92 | * @bank: bank responsible for this interrupt | ||
81 | */ | 93 | */ |
82 | struct exynos_weint_data { | 94 | struct exynos_weint_data { |
83 | struct irq_domain *domain; | 95 | unsigned int irq; |
84 | u32 irq; | 96 | struct samsung_pin_bank *bank; |
97 | }; | ||
98 | |||
99 | /** | ||
100 | * struct exynos_muxed_weint_data: irq specific data for muxed wakeup interrupts | ||
101 | * generated by the external wakeup interrupt controller. | ||
102 | * @nr_banks: count of banks being part of the mux | ||
103 | * @banks: array of banks being part of the mux | ||
104 | */ | ||
105 | struct exynos_muxed_weint_data { | ||
106 | unsigned int nr_banks; | ||
107 | struct samsung_pin_bank *banks[]; | ||
85 | }; | 108 | }; |
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h index dac40ffd5e67..0670d9ea43fa 100644 --- a/drivers/pinctrl/pinctrl-samsung.h +++ b/drivers/pinctrl/pinctrl-samsung.h | |||
@@ -66,6 +66,7 @@ enum pincfg_type { | |||
66 | * @EINT_TYPE_NONE: bank does not support external interrupts | 66 | * @EINT_TYPE_NONE: bank does not support external interrupts |
67 | * @EINT_TYPE_GPIO: bank supportes external gpio interrupts | 67 | * @EINT_TYPE_GPIO: bank supportes external gpio interrupts |
68 | * @EINT_TYPE_WKUP: bank supportes external wakeup interrupts | 68 | * @EINT_TYPE_WKUP: bank supportes external wakeup interrupts |
69 | * @EINT_TYPE_WKUP_MUX: bank supports multiplexed external wakeup interrupts | ||
69 | * | 70 | * |
70 | * Samsung GPIO controller groups all the available pins into banks. The pins | 71 | * Samsung GPIO controller groups all the available pins into banks. The pins |
71 | * in a pin bank can support external gpio interrupts or external wakeup | 72 | * in a pin bank can support external gpio interrupts or external wakeup |
@@ -78,6 +79,7 @@ enum eint_type { | |||
78 | EINT_TYPE_NONE, | 79 | EINT_TYPE_NONE, |
79 | EINT_TYPE_GPIO, | 80 | EINT_TYPE_GPIO, |
80 | EINT_TYPE_WKUP, | 81 | EINT_TYPE_WKUP, |
82 | EINT_TYPE_WKUP_MUX, | ||
81 | }; | 83 | }; |
82 | 84 | ||
83 | /* maximum length of a pin in pin descriptor (example: "gpa0-0") */ | 85 | /* maximum length of a pin in pin descriptor (example: "gpa0-0") */ |
@@ -143,7 +145,6 @@ struct samsung_pin_bank { | |||
143 | * @nr_banks: number of pin banks. | 145 | * @nr_banks: number of pin banks. |
144 | * @base: starting system wide pin number. | 146 | * @base: starting system wide pin number. |
145 | * @nr_pins: number of pins supported by the controller. | 147 | * @nr_pins: number of pins supported by the controller. |
146 | * @nr_wint: number of external wakeup interrupts supported. | ||
147 | * @geint_con: offset of the ext-gpio controller registers. | 148 | * @geint_con: offset of the ext-gpio controller registers. |
148 | * @geint_mask: offset of the ext-gpio interrupt mask registers. | 149 | * @geint_mask: offset of the ext-gpio interrupt mask registers. |
149 | * @geint_pend: offset of the ext-gpio interrupt pending registers. | 150 | * @geint_pend: offset of the ext-gpio interrupt pending registers. |
@@ -163,7 +164,6 @@ struct samsung_pin_ctrl { | |||
163 | 164 | ||
164 | u32 base; | 165 | u32 base; |
165 | u32 nr_pins; | 166 | u32 nr_pins; |
166 | u32 nr_wint; | ||
167 | 167 | ||
168 | u32 geint_con; | 168 | u32 geint_con; |
169 | u32 geint_mask; | 169 | u32 geint_mask; |
@@ -206,8 +206,6 @@ struct samsung_pinctrl_drv_data { | |||
206 | unsigned int nr_groups; | 206 | unsigned int nr_groups; |
207 | const struct samsung_pmx_func *pmx_functions; | 207 | const struct samsung_pmx_func *pmx_functions; |
208 | unsigned int nr_functions; | 208 | unsigned int nr_functions; |
209 | |||
210 | struct irq_domain *wkup_irqd; | ||
211 | }; | 209 | }; |
212 | 210 | ||
213 | /** | 211 | /** |