3232#include "pinctrl-samsung.h"
3333#include "pinctrl-exynos.h"
3434
35+ #define MAX_WAKEUP_REG 3
36+
3537struct exynos_irq_chip {
3638 struct irq_chip chip ;
3739
3840 u32 eint_con ;
3941 u32 eint_mask ;
4042 u32 eint_pend ;
41- u32 * eint_wake_mask_value ;
43+ u32 eint_num_wakeup_reg ;
4244 u32 eint_wake_mask_reg ;
4345 void (* set_eint_wakeup_mask )(struct samsung_pinctrl_drv_data * drvdata ,
4446 struct exynos_irq_chip * irq_chip );
4547};
4648
49+ static u32 eint_wake_mask_values [MAX_WAKEUP_REG ] = { EXYNOS_EINT_WAKEUP_MASK_DISABLED ,
50+ EXYNOS_EINT_WAKEUP_MASK_DISABLED ,
51+ EXYNOS_EINT_WAKEUP_MASK_DISABLED };
52+
4753static inline struct exynos_irq_chip * to_exynos_irq_chip (struct irq_chip * chip )
4854{
4955 return container_of (chip , struct exynos_irq_chip , chip );
@@ -307,7 +313,7 @@ static const struct exynos_irq_chip exynos_gpio_irq_chip __initconst = {
307313 .eint_con = EXYNOS_GPIO_ECON_OFFSET ,
308314 .eint_mask = EXYNOS_GPIO_EMASK_OFFSET ,
309315 .eint_pend = EXYNOS_GPIO_EPEND_OFFSET ,
310- /* eint_wake_mask_value not used */
316+ /* eint_wake_mask_values not used */
311317};
312318
313319static int exynos_eint_irq_map (struct irq_domain * h , unsigned int virq ,
@@ -467,20 +473,65 @@ __init int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
467473 return ret ;
468474}
469475
476+ #define BITS_PER_U32 32
477+ static int gs101_wkup_irq_set_wake (struct irq_data * irqd , unsigned int on )
478+ {
479+ struct samsung_pin_bank * bank = irq_data_get_irq_chip_data (irqd );
480+ struct samsung_pinctrl_drv_data * d = bank -> drvdata ;
481+ u32 bit , wakeup_reg , shift ;
482+
483+ bit = bank -> eint_num + irqd -> hwirq ;
484+ wakeup_reg = bit / BITS_PER_U32 ;
485+ shift = bit - (wakeup_reg * BITS_PER_U32 );
486+
487+ if (!on )
488+ eint_wake_mask_values [wakeup_reg ] |= BIT_U32 (shift );
489+ else
490+ eint_wake_mask_values [wakeup_reg ] &= ~BIT_U32 (shift );
491+
492+ dev_info (d -> dev , "wake %s for irq %d\n" , str_enabled_disabled (on ),
493+ irqd -> irq );
494+
495+ return 0 ;
496+ }
497+
498+ static void
499+ gs101_pinctrl_set_eint_wakeup_mask (struct samsung_pinctrl_drv_data * drvdata ,
500+ struct exynos_irq_chip * irq_chip )
501+ {
502+ struct regmap * pmu_regs ;
503+
504+ if (!drvdata -> retention_ctrl || !drvdata -> retention_ctrl -> priv ) {
505+ dev_warn (drvdata -> dev ,
506+ "No PMU syscon available. Wake-up mask will not be set.\n" );
507+ return ;
508+ }
509+
510+ pmu_regs = drvdata -> retention_ctrl -> priv ;
511+
512+ dev_dbg (drvdata -> dev , "Setting external wakeup interrupt mask:\n" );
513+
514+ for (int i = 0 ; i < irq_chip -> eint_num_wakeup_reg ; i ++ ) {
515+ dev_dbg (drvdata -> dev , "\tWAKEUP_MASK%d[0x%X] value[0x%X]\n" ,
516+ i , irq_chip -> eint_wake_mask_reg + i * 4 ,
517+ eint_wake_mask_values [i ]);
518+ regmap_write (pmu_regs , irq_chip -> eint_wake_mask_reg + i * 4 ,
519+ eint_wake_mask_values [i ]);
520+ }
521+ }
522+
470523static int exynos_wkup_irq_set_wake (struct irq_data * irqd , unsigned int on )
471524{
472- struct irq_chip * chip = irq_data_get_irq_chip (irqd );
473- struct exynos_irq_chip * our_chip = to_exynos_irq_chip (chip );
474525 struct samsung_pin_bank * bank = irq_data_get_irq_chip_data (irqd );
475526 unsigned long bit = 1UL << (2 * bank -> eint_offset + irqd -> hwirq );
476527
477528 pr_info ("wake %s for irq %u (%s-%lu)\n" , str_enabled_disabled (on ),
478529 irqd -> irq , bank -> name , irqd -> hwirq );
479530
480531 if (!on )
481- * our_chip -> eint_wake_mask_value |= bit ;
532+ eint_wake_mask_values [ 0 ] |= bit ;
482533 else
483- * our_chip -> eint_wake_mask_value &= ~bit ;
534+ eint_wake_mask_values [ 0 ] &= ~bit ;
484535
485536 return 0 ;
486537}
@@ -500,10 +551,10 @@ exynos_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
500551 pmu_regs = drvdata -> retention_ctrl -> priv ;
501552 dev_info (drvdata -> dev ,
502553 "Setting external wakeup interrupt mask: 0x%x\n" ,
503- * irq_chip -> eint_wake_mask_value );
554+ eint_wake_mask_values [ 0 ] );
504555
505556 regmap_write (pmu_regs , irq_chip -> eint_wake_mask_reg ,
506- * irq_chip -> eint_wake_mask_value );
557+ eint_wake_mask_values [ 0 ] );
507558}
508559
509560static void
@@ -522,11 +573,10 @@ s5pv210_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
522573
523574 clk_base = (void __iomem * ) drvdata -> retention_ctrl -> priv ;
524575
525- __raw_writel (* irq_chip -> eint_wake_mask_value ,
576+ __raw_writel (eint_wake_mask_values [ 0 ] ,
526577 clk_base + irq_chip -> eint_wake_mask_reg );
527578}
528579
529- static u32 eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED ;
530580/*
531581 * irq_chip for wakeup interrupts
532582 */
@@ -544,7 +594,7 @@ static const struct exynos_irq_chip s5pv210_wkup_irq_chip __initconst = {
544594 .eint_con = EXYNOS_WKUP_ECON_OFFSET ,
545595 .eint_mask = EXYNOS_WKUP_EMASK_OFFSET ,
546596 .eint_pend = EXYNOS_WKUP_EPEND_OFFSET ,
547- .eint_wake_mask_value = & eint_wake_mask_value ,
597+ .eint_num_wakeup_reg = 1 ,
548598 /* Only differences with exynos4210_wkup_irq_chip: */
549599 .eint_wake_mask_reg = S5PV210_EINT_WAKEUP_MASK ,
550600 .set_eint_wakeup_mask = s5pv210_pinctrl_set_eint_wakeup_mask ,
@@ -564,7 +614,7 @@ static const struct exynos_irq_chip exynos4210_wkup_irq_chip __initconst = {
564614 .eint_con = EXYNOS_WKUP_ECON_OFFSET ,
565615 .eint_mask = EXYNOS_WKUP_EMASK_OFFSET ,
566616 .eint_pend = EXYNOS_WKUP_EPEND_OFFSET ,
567- .eint_wake_mask_value = & eint_wake_mask_value ,
617+ .eint_num_wakeup_reg = 1 ,
568618 .eint_wake_mask_reg = EXYNOS_EINT_WAKEUP_MASK ,
569619 .set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask ,
570620};
@@ -583,7 +633,7 @@ static const struct exynos_irq_chip exynos7_wkup_irq_chip __initconst = {
583633 .eint_con = EXYNOS7_WKUP_ECON_OFFSET ,
584634 .eint_mask = EXYNOS7_WKUP_EMASK_OFFSET ,
585635 .eint_pend = EXYNOS7_WKUP_EPEND_OFFSET ,
586- .eint_wake_mask_value = & eint_wake_mask_value ,
636+ .eint_num_wakeup_reg = 1 ,
587637 .eint_wake_mask_reg = EXYNOS5433_EINT_WAKEUP_MASK ,
588638 .set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask ,
589639};
@@ -599,13 +649,34 @@ static const struct exynos_irq_chip exynosautov920_wkup_irq_chip __initconst = {
599649 .irq_request_resources = exynos_irq_request_resources ,
600650 .irq_release_resources = exynos_irq_release_resources ,
601651 },
602- .eint_wake_mask_value = & eint_wake_mask_value ,
652+ .eint_num_wakeup_reg = 1 ,
603653 .eint_wake_mask_reg = EXYNOS5433_EINT_WAKEUP_MASK ,
604654 .set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask ,
605655};
606656
657+ static const struct exynos_irq_chip gs101_wkup_irq_chip __initconst = {
658+ .chip = {
659+ .name = "gs101_wkup_irq_chip" ,
660+ .irq_unmask = exynos_irq_unmask ,
661+ .irq_mask = exynos_irq_mask ,
662+ .irq_ack = exynos_irq_ack ,
663+ .irq_set_type = exynos_irq_set_type ,
664+ .irq_set_wake = gs101_wkup_irq_set_wake ,
665+ .irq_request_resources = exynos_irq_request_resources ,
666+ .irq_release_resources = exynos_irq_release_resources ,
667+ },
668+ .eint_con = EXYNOS7_WKUP_ECON_OFFSET ,
669+ .eint_mask = EXYNOS7_WKUP_EMASK_OFFSET ,
670+ .eint_pend = EXYNOS7_WKUP_EPEND_OFFSET ,
671+ .eint_num_wakeup_reg = 3 ,
672+ .eint_wake_mask_reg = GS101_EINT_WAKEUP_MASK ,
673+ .set_eint_wakeup_mask = gs101_pinctrl_set_eint_wakeup_mask ,
674+ };
675+
607676/* list of external wakeup controllers supported */
608677static const struct of_device_id exynos_wkup_irq_ids [] = {
678+ { .compatible = "google,gs101-wakeup-eint" ,
679+ .data = & gs101_wkup_irq_chip },
609680 { .compatible = "samsung,s5pv210-wakeup-eint" ,
610681 .data = & s5pv210_wkup_irq_chip },
611682 { .compatible = "samsung,exynos4210-wakeup-eint" ,
@@ -688,6 +759,7 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc)
688759 chained_irq_exit (chip , desc );
689760}
690761
762+ static int eint_num ;
691763/*
692764 * exynos_eint_wkup_init() - setup handling of external wakeup interrupts.
693765 * @d: driver data of samsung pinctrl driver.
@@ -736,6 +808,9 @@ __init int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
736808 return - ENXIO ;
737809 }
738810
811+ bank -> eint_num = eint_num ;
812+ eint_num = eint_num + bank -> nr_pins ;
813+
739814 if (!fwnode_property_present (bank -> fwnode , "interrupts" )) {
740815 bank -> eint_type = EINT_TYPE_WKUP_MUX ;
741816 ++ muxed_banks ;
0 commit comments