1515#include <linux/slab.h>
1616#include <linux/syscore_ops.h>
1717
18- #define CIRQ_ACK 0x40
19- #define CIRQ_MASK_SET 0xc0
20- #define CIRQ_MASK_CLR 0x100
21- #define CIRQ_SENS_SET 0x180
22- #define CIRQ_SENS_CLR 0x1c0
23- #define CIRQ_POL_SET 0x240
24- #define CIRQ_POL_CLR 0x280
25- #define CIRQ_CONTROL 0x300
18+ enum mtk_cirq_regoffs_index {
19+ CIRQ_STA ,
20+ CIRQ_ACK ,
21+ CIRQ_MASK_SET ,
22+ CIRQ_MASK_CLR ,
23+ CIRQ_SENS_SET ,
24+ CIRQ_SENS_CLR ,
25+ CIRQ_POL_SET ,
26+ CIRQ_POL_CLR ,
27+ CIRQ_CONTROL
28+ };
29+
30+ static const u32 mtk_cirq_regoffs_v1 [] = {
31+ [CIRQ_STA ] = 0x0 ,
32+ [CIRQ_ACK ] = 0x40 ,
33+ [CIRQ_MASK_SET ] = 0xc0 ,
34+ [CIRQ_MASK_CLR ] = 0x100 ,
35+ [CIRQ_SENS_SET ] = 0x180 ,
36+ [CIRQ_SENS_CLR ] = 0x1c0 ,
37+ [CIRQ_POL_SET ] = 0x240 ,
38+ [CIRQ_POL_CLR ] = 0x280 ,
39+ [CIRQ_CONTROL ] = 0x300 ,
40+ };
41+
42+ static const u32 mtk_cirq_regoffs_v2 [] = {
43+ [CIRQ_STA ] = 0x0 ,
44+ [CIRQ_ACK ] = 0x80 ,
45+ [CIRQ_MASK_SET ] = 0x180 ,
46+ [CIRQ_MASK_CLR ] = 0x200 ,
47+ [CIRQ_SENS_SET ] = 0x300 ,
48+ [CIRQ_SENS_CLR ] = 0x380 ,
49+ [CIRQ_POL_SET ] = 0x480 ,
50+ [CIRQ_POL_CLR ] = 0x500 ,
51+ [CIRQ_CONTROL ] = 0x600 ,
52+ };
2653
2754#define CIRQ_EN 0x1
2855#define CIRQ_EDGE 0x2
@@ -32,18 +59,32 @@ struct mtk_cirq_chip_data {
3259 void __iomem * base ;
3360 unsigned int ext_irq_start ;
3461 unsigned int ext_irq_end ;
62+ const u32 * offsets ;
3563 struct irq_domain * domain ;
3664};
3765
3866static struct mtk_cirq_chip_data * cirq_data ;
3967
40- static void mtk_cirq_write_mask (struct irq_data * data , unsigned int offset )
68+ static void __iomem * mtk_cirq_reg (struct mtk_cirq_chip_data * chip_data ,
69+ enum mtk_cirq_regoffs_index idx )
70+ {
71+ return chip_data -> base + chip_data -> offsets [idx ];
72+ }
73+
74+ static void __iomem * mtk_cirq_irq_reg (struct mtk_cirq_chip_data * chip_data ,
75+ enum mtk_cirq_regoffs_index idx ,
76+ unsigned int cirq_num )
77+ {
78+ return mtk_cirq_reg (chip_data , idx ) + (cirq_num / 32 ) * 4 ;
79+ }
80+
81+ static void mtk_cirq_write_mask (struct irq_data * data , enum mtk_cirq_regoffs_index idx )
4182{
4283 struct mtk_cirq_chip_data * chip_data = data -> chip_data ;
4384 unsigned int cirq_num = data -> hwirq ;
4485 u32 mask = 1 << (cirq_num % 32 );
4586
46- writel_relaxed (mask , chip_data -> base + offset + ( cirq_num / 32 ) * 4 );
87+ writel_relaxed (mask , mtk_cirq_irq_reg ( chip_data , idx , cirq_num ) );
4788}
4889
4990static void mtk_cirq_mask (struct irq_data * data )
@@ -160,6 +201,7 @@ static const struct irq_domain_ops cirq_domain_ops = {
160201#ifdef CONFIG_PM_SLEEP
161202static int mtk_cirq_suspend (void )
162203{
204+ void __iomem * reg ;
163205 u32 value , mask ;
164206 unsigned int irq , hwirq_num ;
165207 bool pending , masked ;
@@ -200,31 +242,34 @@ static int mtk_cirq_suspend(void)
200242 continue ;
201243 }
202244
245+ reg = mtk_cirq_irq_reg (cirq_data , CIRQ_ACK , i );
203246 mask = 1 << (i % 32 );
204- writel_relaxed (mask , cirq_data -> base + CIRQ_ACK + ( i / 32 ) * 4 );
247+ writel_relaxed (mask , reg );
205248 }
206249
207250 /* set edge_only mode, record edge-triggerd interrupts */
208251 /* enable cirq */
209- value = readl_relaxed (cirq_data -> base + CIRQ_CONTROL );
252+ reg = mtk_cirq_reg (cirq_data , CIRQ_CONTROL );
253+ value = readl_relaxed (reg );
210254 value |= (CIRQ_EDGE | CIRQ_EN );
211- writel_relaxed (value , cirq_data -> base + CIRQ_CONTROL );
255+ writel_relaxed (value , reg );
212256
213257 return 0 ;
214258}
215259
216260static void mtk_cirq_resume (void )
217261{
262+ void __iomem * reg = mtk_cirq_reg (cirq_data , CIRQ_CONTROL );
218263 u32 value ;
219264
220265 /* flush recorded interrupts, will send signals to parent controller */
221- value = readl_relaxed (cirq_data -> base + CIRQ_CONTROL );
222- writel_relaxed (value | CIRQ_FLUSH , cirq_data -> base + CIRQ_CONTROL );
266+ value = readl_relaxed (reg );
267+ writel_relaxed (value | CIRQ_FLUSH , reg );
223268
224269 /* disable cirq */
225- value = readl_relaxed (cirq_data -> base + CIRQ_CONTROL );
270+ value = readl_relaxed (reg );
226271 value &= ~(CIRQ_EDGE | CIRQ_EN );
227- writel_relaxed (value , cirq_data -> base + CIRQ_CONTROL );
272+ writel_relaxed (value , reg );
228273}
229274
230275static struct syscore_ops mtk_cirq_syscore_ops = {
@@ -240,10 +285,19 @@ static void mtk_cirq_syscore_init(void)
240285static inline void mtk_cirq_syscore_init (void ) {}
241286#endif
242287
288+ static const struct of_device_id mtk_cirq_of_match [] = {
289+ { .compatible = "mediatek,mt2701-cirq" , .data = & mtk_cirq_regoffs_v1 },
290+ { .compatible = "mediatek,mt8135-cirq" , .data = & mtk_cirq_regoffs_v1 },
291+ { .compatible = "mediatek,mt8173-cirq" , .data = & mtk_cirq_regoffs_v1 },
292+ { .compatible = "mediatek,mt8192-cirq" , .data = & mtk_cirq_regoffs_v2 },
293+ { /* sentinel */ }
294+ };
295+
243296static int __init mtk_cirq_of_init (struct device_node * node ,
244297 struct device_node * parent )
245298{
246299 struct irq_domain * domain , * domain_parent ;
300+ const struct of_device_id * match ;
247301 unsigned int irq_num ;
248302 int ret ;
249303
@@ -274,6 +328,13 @@ static int __init mtk_cirq_of_init(struct device_node *node,
274328 if (ret )
275329 goto out_unmap ;
276330
331+ match = of_match_node (mtk_cirq_of_match , node );
332+ if (!match ) {
333+ ret = - ENODEV ;
334+ goto out_unmap ;
335+ }
336+ cirq_data -> offsets = match -> data ;
337+
277338 irq_num = cirq_data -> ext_irq_end - cirq_data -> ext_irq_start + 1 ;
278339 domain = irq_domain_add_hierarchy (domain_parent , 0 ,
279340 irq_num , node ,
0 commit comments