13
13
// the Samsung pinctrl/gpiolib driver. It also includes the implementation of
14
14
// external gpio and wakeup interrupt support.
15
15
16
+ #include <linux/clk.h>
16
17
#include <linux/device.h>
17
18
#include <linux/interrupt.h>
18
19
#include <linux/irqdomain.h>
@@ -61,13 +62,21 @@ static void exynos_irq_mask(struct irq_data *irqd)
61
62
else
62
63
reg_mask = our_chip -> eint_mask + bank -> eint_offset ;
63
64
65
+ if (clk_enable (bank -> drvdata -> pclk )) {
66
+ dev_err (bank -> gpio_chip .parent ,
67
+ "unable to enable clock for masking IRQ\n" );
68
+ return ;
69
+ }
70
+
64
71
raw_spin_lock_irqsave (& bank -> slock , flags );
65
72
66
73
mask = readl (bank -> eint_base + reg_mask );
67
74
mask |= 1 << irqd -> hwirq ;
68
75
writel (mask , bank -> eint_base + reg_mask );
69
76
70
77
raw_spin_unlock_irqrestore (& bank -> slock , flags );
78
+
79
+ clk_disable (bank -> drvdata -> pclk );
71
80
}
72
81
73
82
static void exynos_irq_ack (struct irq_data * irqd )
@@ -82,7 +91,15 @@ static void exynos_irq_ack(struct irq_data *irqd)
82
91
else
83
92
reg_pend = our_chip -> eint_pend + bank -> eint_offset ;
84
93
94
+ if (clk_enable (bank -> drvdata -> pclk )) {
95
+ dev_err (bank -> gpio_chip .parent ,
96
+ "unable to enable clock to ack IRQ\n" );
97
+ return ;
98
+ }
99
+
85
100
writel (1 << irqd -> hwirq , bank -> eint_base + reg_pend );
101
+
102
+ clk_disable (bank -> drvdata -> pclk );
86
103
}
87
104
88
105
static void exynos_irq_unmask (struct irq_data * irqd )
@@ -110,13 +127,21 @@ static void exynos_irq_unmask(struct irq_data *irqd)
110
127
else
111
128
reg_mask = our_chip -> eint_mask + bank -> eint_offset ;
112
129
130
+ if (clk_enable (bank -> drvdata -> pclk )) {
131
+ dev_err (bank -> gpio_chip .parent ,
132
+ "unable to enable clock for unmasking IRQ\n" );
133
+ return ;
134
+ }
135
+
113
136
raw_spin_lock_irqsave (& bank -> slock , flags );
114
137
115
138
mask = readl (bank -> eint_base + reg_mask );
116
139
mask &= ~(1 << irqd -> hwirq );
117
140
writel (mask , bank -> eint_base + reg_mask );
118
141
119
142
raw_spin_unlock_irqrestore (& bank -> slock , flags );
143
+
144
+ clk_disable (bank -> drvdata -> pclk );
120
145
}
121
146
122
147
static int exynos_irq_set_type (struct irq_data * irqd , unsigned int type )
@@ -127,6 +152,7 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
127
152
unsigned int shift = EXYNOS_EINT_CON_LEN * irqd -> hwirq ;
128
153
unsigned int con , trig_type ;
129
154
unsigned long reg_con ;
155
+ int ret ;
130
156
131
157
switch (type ) {
132
158
case IRQ_TYPE_EDGE_RISING :
@@ -159,11 +185,20 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
159
185
else
160
186
reg_con = our_chip -> eint_con + bank -> eint_offset ;
161
187
188
+ ret = clk_enable (bank -> drvdata -> pclk );
189
+ if (ret ) {
190
+ dev_err (bank -> gpio_chip .parent ,
191
+ "unable to enable clock for configuring IRQ type\n" );
192
+ return ret ;
193
+ }
194
+
162
195
con = readl (bank -> eint_base + reg_con );
163
196
con &= ~(EXYNOS_EINT_CON_MASK << shift );
164
197
con |= trig_type << shift ;
165
198
writel (con , bank -> eint_base + reg_con );
166
199
200
+ clk_disable (bank -> drvdata -> pclk );
201
+
167
202
return 0 ;
168
203
}
169
204
@@ -200,6 +235,14 @@ static int exynos_irq_request_resources(struct irq_data *irqd)
200
235
shift = irqd -> hwirq * bank_type -> fld_width [PINCFG_TYPE_FUNC ];
201
236
mask = (1 << bank_type -> fld_width [PINCFG_TYPE_FUNC ]) - 1 ;
202
237
238
+ ret = clk_enable (bank -> drvdata -> pclk );
239
+ if (ret ) {
240
+ dev_err (bank -> gpio_chip .parent ,
241
+ "unable to enable clock for configuring pin %s-%lu\n" ,
242
+ bank -> name , irqd -> hwirq );
243
+ return ret ;
244
+ }
245
+
203
246
raw_spin_lock_irqsave (& bank -> slock , flags );
204
247
205
248
con = readl (bank -> pctl_base + reg_con );
@@ -209,6 +252,8 @@ static int exynos_irq_request_resources(struct irq_data *irqd)
209
252
210
253
raw_spin_unlock_irqrestore (& bank -> slock , flags );
211
254
255
+ clk_disable (bank -> drvdata -> pclk );
256
+
212
257
return 0 ;
213
258
}
214
259
@@ -223,6 +268,13 @@ static void exynos_irq_release_resources(struct irq_data *irqd)
223
268
shift = irqd -> hwirq * bank_type -> fld_width [PINCFG_TYPE_FUNC ];
224
269
mask = (1 << bank_type -> fld_width [PINCFG_TYPE_FUNC ]) - 1 ;
225
270
271
+ if (clk_enable (bank -> drvdata -> pclk )) {
272
+ dev_err (bank -> gpio_chip .parent ,
273
+ "unable to enable clock for deconfiguring pin %s-%lu\n" ,
274
+ bank -> name , irqd -> hwirq );
275
+ return ;
276
+ }
277
+
226
278
raw_spin_lock_irqsave (& bank -> slock , flags );
227
279
228
280
con = readl (bank -> pctl_base + reg_con );
@@ -232,6 +284,8 @@ static void exynos_irq_release_resources(struct irq_data *irqd)
232
284
233
285
raw_spin_unlock_irqrestore (& bank -> slock , flags );
234
286
287
+ clk_disable (bank -> drvdata -> pclk );
288
+
235
289
gpiochip_unlock_as_irq (& bank -> gpio_chip , irqd -> hwirq );
236
290
}
237
291
@@ -281,10 +335,19 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
281
335
unsigned int svc , group , pin ;
282
336
int ret ;
283
337
338
+ if (clk_enable (bank -> drvdata -> pclk )) {
339
+ dev_err (bank -> gpio_chip .parent ,
340
+ "unable to enable clock for handling IRQ\n" );
341
+ return IRQ_NONE ;
342
+ }
343
+
284
344
if (bank -> eint_con_offset )
285
345
svc = readl (bank -> eint_base + EXYNOSAUTO_SVC_OFFSET );
286
346
else
287
347
svc = readl (bank -> eint_base + EXYNOS_SVC_OFFSET );
348
+
349
+ clk_disable (bank -> drvdata -> pclk );
350
+
288
351
group = EXYNOS_SVC_GROUP (svc );
289
352
pin = svc & EXYNOS_SVC_NUM_MASK ;
290
353
@@ -563,6 +626,20 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc)
563
626
564
627
chained_irq_enter (chip , desc );
565
628
629
+ /*
630
+ * just enable the clock once here, to avoid an enable/disable dance for
631
+ * each bank.
632
+ */
633
+ if (eintd -> nr_banks ) {
634
+ struct samsung_pin_bank * b = eintd -> banks [0 ];
635
+
636
+ if (clk_enable (b -> drvdata -> pclk )) {
637
+ dev_err (b -> gpio_chip .parent ,
638
+ "unable to enable clock for pending IRQs\n" );
639
+ return ;
640
+ }
641
+ }
642
+
566
643
for (i = 0 ; i < eintd -> nr_banks ; ++ i ) {
567
644
struct samsung_pin_bank * b = eintd -> banks [i ];
568
645
pend = readl (b -> eint_base + b -> irq_chip -> eint_pend
@@ -572,6 +649,9 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc)
572
649
exynos_irq_demux_eint (pend & ~mask , b -> irq_domain );
573
650
}
574
651
652
+ if (eintd -> nr_banks )
653
+ clk_disable (eintd -> banks [0 ]-> drvdata -> pclk );
654
+
575
655
chained_irq_exit (chip , desc );
576
656
}
577
657
@@ -695,6 +775,12 @@ static void exynos_pinctrl_suspend_bank(
695
775
struct exynos_eint_gpio_save * save = bank -> soc_priv ;
696
776
const void __iomem * regs = bank -> eint_base ;
697
777
778
+ if (clk_enable (bank -> drvdata -> pclk )) {
779
+ dev_err (bank -> gpio_chip .parent ,
780
+ "unable to enable clock for saving state\n" );
781
+ return ;
782
+ }
783
+
698
784
save -> eint_con = readl (regs + EXYNOS_GPIO_ECON_OFFSET
699
785
+ bank -> eint_offset );
700
786
save -> eint_fltcon0 = readl (regs + EXYNOS_GPIO_EFLTCON_OFFSET
@@ -704,6 +790,8 @@ static void exynos_pinctrl_suspend_bank(
704
790
save -> eint_mask = readl (regs + bank -> irq_chip -> eint_mask
705
791
+ bank -> eint_offset );
706
792
793
+ clk_disable (bank -> drvdata -> pclk );
794
+
707
795
pr_debug ("%s: save con %#010x\n" , bank -> name , save -> eint_con );
708
796
pr_debug ("%s: save fltcon0 %#010x\n" , bank -> name , save -> eint_fltcon0 );
709
797
pr_debug ("%s: save fltcon1 %#010x\n" , bank -> name , save -> eint_fltcon1 );
@@ -716,9 +804,17 @@ static void exynosauto_pinctrl_suspend_bank(struct samsung_pinctrl_drv_data *drv
716
804
struct exynos_eint_gpio_save * save = bank -> soc_priv ;
717
805
const void __iomem * regs = bank -> eint_base ;
718
806
807
+ if (clk_enable (bank -> drvdata -> pclk )) {
808
+ dev_err (bank -> gpio_chip .parent ,
809
+ "unable to enable clock for saving state\n" );
810
+ return ;
811
+ }
812
+
719
813
save -> eint_con = readl (regs + bank -> pctl_offset + bank -> eint_con_offset );
720
814
save -> eint_mask = readl (regs + bank -> pctl_offset + bank -> eint_mask_offset );
721
815
816
+ clk_disable (bank -> drvdata -> pclk );
817
+
722
818
pr_debug ("%s: save con %#010x\n" , bank -> name , save -> eint_con );
723
819
pr_debug ("%s: save mask %#010x\n" , bank -> name , save -> eint_mask );
724
820
}
@@ -753,6 +849,12 @@ static void exynos_pinctrl_resume_bank(
753
849
struct exynos_eint_gpio_save * save = bank -> soc_priv ;
754
850
void __iomem * regs = bank -> eint_base ;
755
851
852
+ if (clk_enable (bank -> drvdata -> pclk )) {
853
+ dev_err (bank -> gpio_chip .parent ,
854
+ "unable to enable clock for restoring state\n" );
855
+ return ;
856
+ }
857
+
756
858
pr_debug ("%s: con %#010x => %#010x\n" , bank -> name ,
757
859
readl (regs + EXYNOS_GPIO_ECON_OFFSET
758
860
+ bank -> eint_offset ), save -> eint_con );
@@ -774,6 +876,8 @@ static void exynos_pinctrl_resume_bank(
774
876
+ 2 * bank -> eint_offset + 4 );
775
877
writel (save -> eint_mask , regs + bank -> irq_chip -> eint_mask
776
878
+ bank -> eint_offset );
879
+
880
+ clk_disable (bank -> drvdata -> pclk );
777
881
}
778
882
779
883
static void exynosauto_pinctrl_resume_bank (struct samsung_pinctrl_drv_data * drvdata ,
@@ -782,13 +886,21 @@ static void exynosauto_pinctrl_resume_bank(struct samsung_pinctrl_drv_data *drvd
782
886
struct exynos_eint_gpio_save * save = bank -> soc_priv ;
783
887
void __iomem * regs = bank -> eint_base ;
784
888
889
+ if (clk_enable (bank -> drvdata -> pclk )) {
890
+ dev_err (bank -> gpio_chip .parent ,
891
+ "unable to enable clock for restoring state\n" );
892
+ return ;
893
+ }
894
+
785
895
pr_debug ("%s: con %#010x => %#010x\n" , bank -> name ,
786
896
readl (regs + bank -> pctl_offset + bank -> eint_con_offset ), save -> eint_con );
787
897
pr_debug ("%s: mask %#010x => %#010x\n" , bank -> name ,
788
898
readl (regs + bank -> pctl_offset + bank -> eint_mask_offset ), save -> eint_mask );
789
899
790
900
writel (save -> eint_con , regs + bank -> pctl_offset + bank -> eint_con_offset );
791
901
writel (save -> eint_mask , regs + bank -> pctl_offset + bank -> eint_mask_offset );
902
+
903
+ clk_disable (bank -> drvdata -> pclk );
792
904
}
793
905
794
906
void exynos_pinctrl_resume (struct samsung_pinctrl_drv_data * drvdata )
0 commit comments