summaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2018-07-25 16:47:03 -0400
committerLinus Walleij <linus.walleij@linaro.org>2018-07-25 16:47:03 -0400
commit8c17dee1706d3bc5861513145b762d1a63abda9f (patch)
treef88084f9c6a96dc5aba0113d31e25d8a0cc387db /drivers/pinctrl
parent238262af08a20e5f1932fcf606b8b84370ac8b77 (diff)
parentb3793159249bb091efce4b1515ce18cdfc4c6e41 (diff)
Merge tag 'samsung-pinctrl-4.19' of https://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/samsung into devel
Samsung pinctrl drivers changes for v4.19 1. Add handling of external wakeup interrupts mask inside the pin controller driver. Existing solution is spread between the driver and machine code. The machine code writes the mask but its value is taken from pin controller driver. This moves everything into pin controller driver allowing later to remove the cross-subsystem interaction. Also this is a necessary step for implementing later Suspend to RAM on ARMv8 Exynos5433. 2. Bring necessary suspend/resume callbacks for Exynos542x and Exynos5260. 3. Document hidden requirement about one external wakeup interrupts device node. 4. Minor documentation cleanups.
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos-arm.c16
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos.c68
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.h11
3 files changed, 94 insertions, 1 deletions
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos-arm.c b/drivers/pinctrl/samsung/pinctrl-exynos-arm.c
index d82820fc349a..44c6b753f692 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos-arm.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos-arm.c
@@ -616,16 +616,22 @@ static const struct samsung_pin_ctrl exynos5260_pin_ctrl[] __initconst = {
616 .nr_banks = ARRAY_SIZE(exynos5260_pin_banks0), 616 .nr_banks = ARRAY_SIZE(exynos5260_pin_banks0),
617 .eint_gpio_init = exynos_eint_gpio_init, 617 .eint_gpio_init = exynos_eint_gpio_init,
618 .eint_wkup_init = exynos_eint_wkup_init, 618 .eint_wkup_init = exynos_eint_wkup_init,
619 .suspend = exynos_pinctrl_suspend,
620 .resume = exynos_pinctrl_resume,
619 }, { 621 }, {
620 /* pin-controller instance 1 data */ 622 /* pin-controller instance 1 data */
621 .pin_banks = exynos5260_pin_banks1, 623 .pin_banks = exynos5260_pin_banks1,
622 .nr_banks = ARRAY_SIZE(exynos5260_pin_banks1), 624 .nr_banks = ARRAY_SIZE(exynos5260_pin_banks1),
623 .eint_gpio_init = exynos_eint_gpio_init, 625 .eint_gpio_init = exynos_eint_gpio_init,
626 .suspend = exynos_pinctrl_suspend,
627 .resume = exynos_pinctrl_resume,
624 }, { 628 }, {
625 /* pin-controller instance 2 data */ 629 /* pin-controller instance 2 data */
626 .pin_banks = exynos5260_pin_banks2, 630 .pin_banks = exynos5260_pin_banks2,
627 .nr_banks = ARRAY_SIZE(exynos5260_pin_banks2), 631 .nr_banks = ARRAY_SIZE(exynos5260_pin_banks2),
628 .eint_gpio_init = exynos_eint_gpio_init, 632 .eint_gpio_init = exynos_eint_gpio_init,
633 .suspend = exynos_pinctrl_suspend,
634 .resume = exynos_pinctrl_resume,
629 }, 635 },
630}; 636};
631 637
@@ -842,30 +848,40 @@ static const struct samsung_pin_ctrl exynos5420_pin_ctrl[] __initconst = {
842 .nr_banks = ARRAY_SIZE(exynos5420_pin_banks0), 848 .nr_banks = ARRAY_SIZE(exynos5420_pin_banks0),
843 .eint_gpio_init = exynos_eint_gpio_init, 849 .eint_gpio_init = exynos_eint_gpio_init,
844 .eint_wkup_init = exynos_eint_wkup_init, 850 .eint_wkup_init = exynos_eint_wkup_init,
851 .suspend = exynos_pinctrl_suspend,
852 .resume = exynos_pinctrl_resume,
845 .retention_data = &exynos5420_retention_data, 853 .retention_data = &exynos5420_retention_data,
846 }, { 854 }, {
847 /* pin-controller instance 1 data */ 855 /* pin-controller instance 1 data */
848 .pin_banks = exynos5420_pin_banks1, 856 .pin_banks = exynos5420_pin_banks1,
849 .nr_banks = ARRAY_SIZE(exynos5420_pin_banks1), 857 .nr_banks = ARRAY_SIZE(exynos5420_pin_banks1),
850 .eint_gpio_init = exynos_eint_gpio_init, 858 .eint_gpio_init = exynos_eint_gpio_init,
859 .suspend = exynos_pinctrl_suspend,
860 .resume = exynos_pinctrl_resume,
851 .retention_data = &exynos5420_retention_data, 861 .retention_data = &exynos5420_retention_data,
852 }, { 862 }, {
853 /* pin-controller instance 2 data */ 863 /* pin-controller instance 2 data */
854 .pin_banks = exynos5420_pin_banks2, 864 .pin_banks = exynos5420_pin_banks2,
855 .nr_banks = ARRAY_SIZE(exynos5420_pin_banks2), 865 .nr_banks = ARRAY_SIZE(exynos5420_pin_banks2),
856 .eint_gpio_init = exynos_eint_gpio_init, 866 .eint_gpio_init = exynos_eint_gpio_init,
867 .suspend = exynos_pinctrl_suspend,
868 .resume = exynos_pinctrl_resume,
857 .retention_data = &exynos5420_retention_data, 869 .retention_data = &exynos5420_retention_data,
858 }, { 870 }, {
859 /* pin-controller instance 3 data */ 871 /* pin-controller instance 3 data */
860 .pin_banks = exynos5420_pin_banks3, 872 .pin_banks = exynos5420_pin_banks3,
861 .nr_banks = ARRAY_SIZE(exynos5420_pin_banks3), 873 .nr_banks = ARRAY_SIZE(exynos5420_pin_banks3),
862 .eint_gpio_init = exynos_eint_gpio_init, 874 .eint_gpio_init = exynos_eint_gpio_init,
875 .suspend = exynos_pinctrl_suspend,
876 .resume = exynos_pinctrl_resume,
863 .retention_data = &exynos5420_retention_data, 877 .retention_data = &exynos5420_retention_data,
864 }, { 878 }, {
865 /* pin-controller instance 4 data */ 879 /* pin-controller instance 4 data */
866 .pin_banks = exynos5420_pin_banks4, 880 .pin_banks = exynos5420_pin_banks4,
867 .nr_banks = ARRAY_SIZE(exynos5420_pin_banks4), 881 .nr_banks = ARRAY_SIZE(exynos5420_pin_banks4),
868 .eint_gpio_init = exynos_eint_gpio_init, 882 .eint_gpio_init = exynos_eint_gpio_init,
883 .suspend = exynos_pinctrl_suspend,
884 .resume = exynos_pinctrl_resume,
869 .retention_data = &exynos4_audio_retention_data, 885 .retention_data = &exynos4_audio_retention_data,
870 }, 886 },
871}; 887};
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index a263ddd94945..40ef14956876 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -25,6 +25,7 @@
25#include <linux/regmap.h> 25#include <linux/regmap.h>
26#include <linux/err.h> 26#include <linux/err.h>
27#include <linux/soc/samsung/exynos-pmu.h> 27#include <linux/soc/samsung/exynos-pmu.h>
28#include <linux/soc/samsung/exynos-regs-pmu.h>
28 29
29#include <dt-bindings/pinctrl/samsung.h> 30#include <dt-bindings/pinctrl/samsung.h>
30 31
@@ -37,6 +38,8 @@ struct exynos_irq_chip {
37 u32 eint_con; 38 u32 eint_con;
38 u32 eint_mask; 39 u32 eint_mask;
39 u32 eint_pend; 40 u32 eint_pend;
41 u32 eint_wake_mask_value;
42 u32 eint_wake_mask_reg;
40}; 43};
41 44
42static inline struct exynos_irq_chip *to_exynos_irq_chip(struct irq_chip *chip) 45static inline struct exynos_irq_chip *to_exynos_irq_chip(struct irq_chip *chip)
@@ -215,6 +218,7 @@ static struct exynos_irq_chip exynos_gpio_irq_chip = {
215 .eint_con = EXYNOS_GPIO_ECON_OFFSET, 218 .eint_con = EXYNOS_GPIO_ECON_OFFSET,
216 .eint_mask = EXYNOS_GPIO_EMASK_OFFSET, 219 .eint_mask = EXYNOS_GPIO_EMASK_OFFSET,
217 .eint_pend = EXYNOS_GPIO_EPEND_OFFSET, 220 .eint_pend = EXYNOS_GPIO_EPEND_OFFSET,
221 /* eint_wake_mask_value not used */
218}; 222};
219 223
220static int exynos_eint_irq_map(struct irq_domain *h, unsigned int virq, 224static int exynos_eint_irq_map(struct irq_domain *h, unsigned int virq,
@@ -330,6 +334,8 @@ u32 exynos_get_eint_wake_mask(void)
330 334
331static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on) 335static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on)
332{ 336{
337 struct irq_chip *chip = irq_data_get_irq_chip(irqd);
338 struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
333 struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); 339 struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
334 unsigned long bit = 1UL << (2 * bank->eint_offset + irqd->hwirq); 340 unsigned long bit = 1UL << (2 * bank->eint_offset + irqd->hwirq);
335 341
@@ -339,6 +345,7 @@ static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on)
339 exynos_eint_wake_mask |= bit; 345 exynos_eint_wake_mask |= bit;
340 else 346 else
341 exynos_eint_wake_mask &= ~bit; 347 exynos_eint_wake_mask &= ~bit;
348 our_chip->eint_wake_mask_value = exynos_eint_wake_mask;
342 349
343 return 0; 350 return 0;
344} 351}
@@ -346,6 +353,25 @@ static int exynos_wkup_irq_set_wake(struct irq_data *irqd, unsigned int on)
346/* 353/*
347 * irq_chip for wakeup interrupts 354 * irq_chip for wakeup interrupts
348 */ 355 */
356static const struct exynos_irq_chip s5pv210_wkup_irq_chip __initconst = {
357 .chip = {
358 .name = "s5pv210_wkup_irq_chip",
359 .irq_unmask = exynos_irq_unmask,
360 .irq_mask = exynos_irq_mask,
361 .irq_ack = exynos_irq_ack,
362 .irq_set_type = exynos_irq_set_type,
363 .irq_set_wake = exynos_wkup_irq_set_wake,
364 .irq_request_resources = exynos_irq_request_resources,
365 .irq_release_resources = exynos_irq_release_resources,
366 },
367 .eint_con = EXYNOS_WKUP_ECON_OFFSET,
368 .eint_mask = EXYNOS_WKUP_EMASK_OFFSET,
369 .eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
370 .eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED,
371 /* Only difference with exynos4210_wkup_irq_chip: */
372 .eint_wake_mask_reg = S5PV210_EINT_WAKEUP_MASK,
373};
374
349static const struct exynos_irq_chip exynos4210_wkup_irq_chip __initconst = { 375static const struct exynos_irq_chip exynos4210_wkup_irq_chip __initconst = {
350 .chip = { 376 .chip = {
351 .name = "exynos4210_wkup_irq_chip", 377 .name = "exynos4210_wkup_irq_chip",
@@ -360,6 +386,8 @@ static const struct exynos_irq_chip exynos4210_wkup_irq_chip __initconst = {
360 .eint_con = EXYNOS_WKUP_ECON_OFFSET, 386 .eint_con = EXYNOS_WKUP_ECON_OFFSET,
361 .eint_mask = EXYNOS_WKUP_EMASK_OFFSET, 387 .eint_mask = EXYNOS_WKUP_EMASK_OFFSET,
362 .eint_pend = EXYNOS_WKUP_EPEND_OFFSET, 388 .eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
389 .eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED,
390 .eint_wake_mask_reg = EXYNOS_EINT_WAKEUP_MASK,
363}; 391};
364 392
365static const struct exynos_irq_chip exynos7_wkup_irq_chip __initconst = { 393static const struct exynos_irq_chip exynos7_wkup_irq_chip __initconst = {
@@ -376,10 +404,14 @@ static const struct exynos_irq_chip exynos7_wkup_irq_chip __initconst = {
376 .eint_con = EXYNOS7_WKUP_ECON_OFFSET, 404 .eint_con = EXYNOS7_WKUP_ECON_OFFSET,
377 .eint_mask = EXYNOS7_WKUP_EMASK_OFFSET, 405 .eint_mask = EXYNOS7_WKUP_EMASK_OFFSET,
378 .eint_pend = EXYNOS7_WKUP_EPEND_OFFSET, 406 .eint_pend = EXYNOS7_WKUP_EPEND_OFFSET,
407 .eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED,
408 .eint_wake_mask_reg = EXYNOS5433_EINT_WAKEUP_MASK,
379}; 409};
380 410
381/* list of external wakeup controllers supported */ 411/* list of external wakeup controllers supported */
382static const struct of_device_id exynos_wkup_irq_ids[] = { 412static const struct of_device_id exynos_wkup_irq_ids[] = {
413 { .compatible = "samsung,s5pv210-wakeup-eint",
414 .data = &s5pv210_wkup_irq_chip },
383 { .compatible = "samsung,exynos4210-wakeup-eint", 415 { .compatible = "samsung,exynos4210-wakeup-eint",
384 .data = &exynos4210_wkup_irq_chip }, 416 .data = &exynos4210_wkup_irq_chip },
385 { .compatible = "samsung,exynos7-wakeup-eint", 417 { .compatible = "samsung,exynos7-wakeup-eint",
@@ -542,6 +574,27 @@ int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
542 return 0; 574 return 0;
543} 575}
544 576
577static void
578exynos_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
579 struct exynos_irq_chip *irq_chip)
580{
581 struct regmap *pmu_regs;
582
583 if (!drvdata->retention_ctrl || !drvdata->retention_ctrl->priv) {
584 dev_warn(drvdata->dev,
585 "No retention data configured bank with external wakeup interrupt. Wake-up mask will not be set.\n");
586 return;
587 }
588
589 pmu_regs = drvdata->retention_ctrl->priv;
590 dev_info(drvdata->dev,
591 "Setting external wakeup interrupt wakeup mask: 0x%x\n",
592 irq_chip->eint_wake_mask_value);
593
594 regmap_write(pmu_regs, irq_chip->eint_wake_mask_reg,
595 irq_chip->eint_wake_mask_value);
596}
597
545static void exynos_pinctrl_suspend_bank( 598static void exynos_pinctrl_suspend_bank(
546 struct samsung_pinctrl_drv_data *drvdata, 599 struct samsung_pinctrl_drv_data *drvdata,
547 struct samsung_pin_bank *bank) 600 struct samsung_pin_bank *bank)
@@ -564,11 +617,24 @@ static void exynos_pinctrl_suspend_bank(
564void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata) 617void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
565{ 618{
566 struct samsung_pin_bank *bank = drvdata->pin_banks; 619 struct samsung_pin_bank *bank = drvdata->pin_banks;
620 struct exynos_irq_chip *irq_chip = NULL;
567 int i; 621 int i;
568 622
569 for (i = 0; i < drvdata->nr_banks; ++i, ++bank) 623 for (i = 0; i < drvdata->nr_banks; ++i, ++bank) {
570 if (bank->eint_type == EINT_TYPE_GPIO) 624 if (bank->eint_type == EINT_TYPE_GPIO)
571 exynos_pinctrl_suspend_bank(drvdata, bank); 625 exynos_pinctrl_suspend_bank(drvdata, bank);
626 else if (bank->eint_type == EINT_TYPE_WKUP) {
627 if (!irq_chip) {
628 irq_chip = bank->irq_chip;
629 exynos_pinctrl_set_eint_wakeup_mask(drvdata,
630 irq_chip);
631 } else if (bank->irq_chip != irq_chip) {
632 dev_warn(drvdata->dev,
633 "More than one external wakeup interrupt chip configured (bank: %s). This is not supported by hardware nor by driver.\n",
634 bank->name);
635 }
636 }
637 }
572} 638}
573 639
574static void exynos_pinctrl_resume_bank( 640static void exynos_pinctrl_resume_bank(
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index f0cda9424dfe..e571bbd7139b 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -223,6 +223,13 @@ struct samsung_retention_data {
223 * interrupts for the controller. 223 * interrupts for the controller.
224 * @eint_wkup_init: platform specific callback to setup the external wakeup 224 * @eint_wkup_init: platform specific callback to setup the external wakeup
225 * interrupts for the controller. 225 * interrupts for the controller.
226 * @suspend: platform specific suspend callback, executed during pin controller
227 * device suspend, see samsung_pinctrl_suspend()
228 * @resume: platform specific resume callback, executed during pin controller
229 * device suspend, see samsung_pinctrl_resume()
230 *
231 * External wakeup interrupts must define at least eint_wkup_init,
232 * retention_data and suspend in order for proper suspend/resume to work.
226 */ 233 */
227struct samsung_pin_ctrl { 234struct samsung_pin_ctrl {
228 const struct samsung_pin_bank_data *pin_banks; 235 const struct samsung_pin_bank_data *pin_banks;
@@ -255,6 +262,10 @@ struct samsung_pin_ctrl {
255 * @pin_base: starting system wide pin number. 262 * @pin_base: starting system wide pin number.
256 * @nr_pins: number of pins supported by the controller. 263 * @nr_pins: number of pins supported by the controller.
257 * @retention_ctrl: retention control runtime data. 264 * @retention_ctrl: retention control runtime data.
265 * @suspend: platform specific suspend callback, executed during pin controller
266 * device suspend, see samsung_pinctrl_suspend()
267 * @resume: platform specific resume callback, executed during pin controller
268 * device suspend, see samsung_pinctrl_resume()
258 */ 269 */
259struct samsung_pinctrl_drv_data { 270struct samsung_pinctrl_drv_data {
260 struct list_head node; 271 struct list_head node;