11// SPDX-License-Identifier: GPL-2.0-or-later
22/*
3- * Aspeed AST24XX, AST25XX, and AST26XX SCU Interrupt Controller
3+ * Aspeed AST24XX, AST25XX, AST26XX, and AST27XX SCU Interrupt Controller
44 * Copyright 2019 IBM Corporation
55 *
66 * Eddie James <eajames@linux.ibm.com>
1717
1818#define ASPEED_SCU_IC_STATUS GENMASK(28, 16)
1919#define ASPEED_SCU_IC_STATUS_SHIFT 16
20+ #define AST2700_SCU_IC_STATUS GENMASK(15, 0)
2021
2122struct aspeed_scu_ic_variant {
2223 const char * compatible ;
2324 unsigned long irq_enable ;
2425 unsigned long irq_shift ;
2526 unsigned int num_irqs ;
27+ unsigned long ier ;
28+ unsigned long isr ;
2629};
2730
28- #define SCU_VARIANT (_compat , _shift , _enable , _num ) { \
31+ #define SCU_VARIANT (_compat , _shift , _enable , _num , _ier , _isr ) { \
2932 .compatible = _compat, \
3033 .irq_shift = _shift, \
3134 .irq_enable = _enable, \
3235 .num_irqs = _num, \
36+ .ier = _ier, \
37+ .isr = _isr, \
3338}
3439
3540static const struct aspeed_scu_ic_variant scu_ic_variants [] __initconst = {
36- SCU_VARIANT ("aspeed,ast2400-scu-ic" , 0 , GENMASK (15 , 0 ), 7 ),
37- SCU_VARIANT ("aspeed,ast2500-scu-ic" , 0 , GENMASK (15 , 0 ), 7 ),
38- SCU_VARIANT ("aspeed,ast2600-scu-ic0" , 0 , GENMASK (5 , 0 ), 6 ),
39- SCU_VARIANT ("aspeed,ast2600-scu-ic1" , 4 , GENMASK (5 , 4 ), 2 ),
41+ SCU_VARIANT ("aspeed,ast2400-scu-ic" , 0 , GENMASK (15 , 0 ), 7 , 0x00 , 0x00 ),
42+ SCU_VARIANT ("aspeed,ast2500-scu-ic" , 0 , GENMASK (15 , 0 ), 7 , 0x00 , 0x00 ),
43+ SCU_VARIANT ("aspeed,ast2600-scu-ic0" , 0 , GENMASK (5 , 0 ), 6 , 0x00 , 0x00 ),
44+ SCU_VARIANT ("aspeed,ast2600-scu-ic1" , 4 , GENMASK (5 , 4 ), 2 , 0x00 , 0x00 ),
45+ SCU_VARIANT ("aspeed,ast2700-scu-ic0" , 0 , GENMASK (3 , 0 ), 4 , 0x00 , 0x04 ),
46+ SCU_VARIANT ("aspeed,ast2700-scu-ic1" , 0 , GENMASK (3 , 0 ), 4 , 0x00 , 0x04 ),
47+ SCU_VARIANT ("aspeed,ast2700-scu-ic2" , 0 , GENMASK (3 , 0 ), 4 , 0x04 , 0x00 ),
48+ SCU_VARIANT ("aspeed,ast2700-scu-ic3" , 0 , GENMASK (1 , 0 ), 2 , 0x04 , 0x00 ),
4049};
4150
4251struct aspeed_scu_ic {
@@ -45,9 +54,16 @@ struct aspeed_scu_ic {
4554 unsigned int num_irqs ;
4655 void __iomem * base ;
4756 struct irq_domain * irq_domain ;
57+ unsigned long ier ;
58+ unsigned long isr ;
4859};
4960
50- static void aspeed_scu_ic_irq_handler (struct irq_desc * desc )
61+ static inline bool scu_has_split_isr (struct aspeed_scu_ic * scu )
62+ {
63+ return scu -> ier != scu -> isr ;
64+ }
65+
66+ static void aspeed_scu_ic_irq_handler_combined (struct irq_desc * desc )
5167{
5268 struct aspeed_scu_ic * scu_ic = irq_desc_get_handler_data (desc );
5369 struct irq_chip * chip = irq_desc_get_chip (desc );
@@ -83,7 +99,34 @@ static void aspeed_scu_ic_irq_handler(struct irq_desc *desc)
8399 chained_irq_exit (chip , desc );
84100}
85101
86- static void aspeed_scu_ic_irq_mask (struct irq_data * data )
102+ static void aspeed_scu_ic_irq_handler_split (struct irq_desc * desc )
103+ {
104+ struct aspeed_scu_ic * scu_ic = irq_desc_get_handler_data (desc );
105+ struct irq_chip * chip = irq_desc_get_chip (desc );
106+ unsigned long bit , enabled , max , status ;
107+ unsigned int sts , mask ;
108+
109+ chained_irq_enter (chip , desc );
110+
111+ mask = scu_ic -> irq_enable ;
112+ sts = readl (scu_ic -> base + scu_ic -> isr );
113+ enabled = sts & scu_ic -> irq_enable ;
114+ sts = readl (scu_ic -> base + scu_ic -> isr );
115+ status = sts & enabled ;
116+
117+ bit = scu_ic -> irq_shift ;
118+ max = scu_ic -> num_irqs + bit ;
119+
120+ for_each_set_bit_from (bit , & status , max ) {
121+ generic_handle_domain_irq (scu_ic -> irq_domain , bit - scu_ic -> irq_shift );
122+ /* Clear interrupt */
123+ writel (BIT (bit ), scu_ic -> base + scu_ic -> isr );
124+ }
125+
126+ chained_irq_exit (chip , desc );
127+ }
128+
129+ static void aspeed_scu_ic_irq_mask_combined (struct irq_data * data )
87130{
88131 struct aspeed_scu_ic * scu_ic = irq_data_get_irq_chip_data (data );
89132 unsigned int bit = BIT (data -> hwirq + scu_ic -> irq_shift );
@@ -97,7 +140,7 @@ static void aspeed_scu_ic_irq_mask(struct irq_data *data)
97140 writel (readl (scu_ic -> base ) & ~mask , scu_ic -> base );
98141}
99142
100- static void aspeed_scu_ic_irq_unmask (struct irq_data * data )
143+ static void aspeed_scu_ic_irq_unmask_combined (struct irq_data * data )
101144{
102145 struct aspeed_scu_ic * scu_ic = irq_data_get_irq_chip_data (data );
103146 unsigned int bit = BIT (data -> hwirq + scu_ic -> irq_shift );
@@ -111,24 +154,52 @@ static void aspeed_scu_ic_irq_unmask(struct irq_data *data)
111154 writel ((readl (scu_ic -> base ) & ~mask ) | bit , scu_ic -> base );
112155}
113156
157+ static void aspeed_scu_ic_irq_mask_split (struct irq_data * data )
158+ {
159+ struct aspeed_scu_ic * scu_ic = irq_data_get_irq_chip_data (data );
160+ unsigned int mask = BIT (data -> hwirq + scu_ic -> irq_shift );
161+
162+ writel (readl (scu_ic -> base ) & ~mask , scu_ic -> base + scu_ic -> ier );
163+ }
164+
165+ static void aspeed_scu_ic_irq_unmask_split (struct irq_data * data )
166+ {
167+ struct aspeed_scu_ic * scu_ic = irq_data_get_irq_chip_data (data );
168+ unsigned int bit = BIT (data -> hwirq + scu_ic -> irq_shift );
169+
170+ writel (readl (scu_ic -> base ) | bit , scu_ic -> base + scu_ic -> ier );
171+ }
172+
114173static int aspeed_scu_ic_irq_set_affinity (struct irq_data * data ,
115174 const struct cpumask * dest ,
116175 bool force )
117176{
118177 return - EINVAL ;
119178}
120179
121- static struct irq_chip aspeed_scu_ic_chip = {
180+ static struct irq_chip aspeed_scu_ic_chip_combined = {
122181 .name = "aspeed-scu-ic" ,
123- .irq_mask = aspeed_scu_ic_irq_mask ,
124- .irq_unmask = aspeed_scu_ic_irq_unmask ,
125- .irq_set_affinity = aspeed_scu_ic_irq_set_affinity ,
182+ .irq_mask = aspeed_scu_ic_irq_mask_combined ,
183+ .irq_unmask = aspeed_scu_ic_irq_unmask_combined ,
184+ .irq_set_affinity = aspeed_scu_ic_irq_set_affinity ,
185+ };
186+
187+ static struct irq_chip aspeed_scu_ic_chip_split = {
188+ .name = "ast2700-scu-ic" ,
189+ .irq_mask = aspeed_scu_ic_irq_mask_split ,
190+ .irq_unmask = aspeed_scu_ic_irq_unmask_split ,
191+ .irq_set_affinity = aspeed_scu_ic_irq_set_affinity ,
126192};
127193
128194static int aspeed_scu_ic_map (struct irq_domain * domain , unsigned int irq ,
129195 irq_hw_number_t hwirq )
130196{
131- irq_set_chip_and_handler (irq , & aspeed_scu_ic_chip , handle_level_irq );
197+ struct aspeed_scu_ic * scu_ic = domain -> host_data ;
198+
199+ if (scu_has_split_isr (scu_ic ))
200+ irq_set_chip_and_handler (irq , & aspeed_scu_ic_chip_split , handle_level_irq );
201+ else
202+ irq_set_chip_and_handler (irq , & aspeed_scu_ic_chip_combined , handle_level_irq );
132203 irq_set_chip_data (irq , domain -> host_data );
133204
134205 return 0 ;
@@ -148,8 +219,14 @@ static int aspeed_scu_ic_of_init_common(struct aspeed_scu_ic *scu_ic,
148219 rc = PTR_ERR (scu_ic -> base );
149220 goto err ;
150221 }
151- writel (ASPEED_SCU_IC_STATUS , scu_ic -> base );
152- writel (0 , scu_ic -> base );
222+
223+ if (scu_has_split_isr (scu_ic )) {
224+ writel (AST2700_SCU_IC_STATUS , scu_ic -> base + scu_ic -> isr );
225+ writel (0 , scu_ic -> base + scu_ic -> ier );
226+ } else {
227+ writel (ASPEED_SCU_IC_STATUS , scu_ic -> base );
228+ writel (0 , scu_ic -> base );
229+ }
153230
154231 irq = irq_of_parse_and_map (node , 0 );
155232 if (!irq ) {
@@ -164,7 +241,9 @@ static int aspeed_scu_ic_of_init_common(struct aspeed_scu_ic *scu_ic,
164241 goto err ;
165242 }
166243
167- irq_set_chained_handler_and_data (irq , aspeed_scu_ic_irq_handler ,
244+ irq_set_chained_handler_and_data (irq , scu_has_split_isr (scu_ic ) ?
245+ aspeed_scu_ic_irq_handler_split :
246+ aspeed_scu_ic_irq_handler_combined ,
168247 scu_ic );
169248
170249 return 0 ;
@@ -199,6 +278,8 @@ static int __init aspeed_scu_ic_of_init(struct device_node *node, struct device_
199278 scu_ic -> irq_enable = variant -> irq_enable ;
200279 scu_ic -> irq_shift = variant -> irq_shift ;
201280 scu_ic -> num_irqs = variant -> num_irqs ;
281+ scu_ic -> ier = variant -> ier ;
282+ scu_ic -> isr = variant -> isr ;
202283
203284 return aspeed_scu_ic_of_init_common (scu_ic , node );
204285}
@@ -207,3 +288,7 @@ IRQCHIP_DECLARE(ast2400_scu_ic, "aspeed,ast2400-scu-ic", aspeed_scu_ic_of_init);
207288IRQCHIP_DECLARE (ast2500_scu_ic , "aspeed,ast2500-scu-ic" , aspeed_scu_ic_of_init );
208289IRQCHIP_DECLARE (ast2600_scu_ic0 , "aspeed,ast2600-scu-ic0" , aspeed_scu_ic_of_init );
209290IRQCHIP_DECLARE (ast2600_scu_ic1 , "aspeed,ast2600-scu-ic1" , aspeed_scu_ic_of_init );
291+ IRQCHIP_DECLARE (ast2700_scu_ic0 , "aspeed,ast2700-scu-ic0" , aspeed_scu_ic_of_init );
292+ IRQCHIP_DECLARE (ast2700_scu_ic1 , "aspeed,ast2700-scu-ic1" , aspeed_scu_ic_of_init );
293+ IRQCHIP_DECLARE (ast2700_scu_ic2 , "aspeed,ast2700-scu-ic2" , aspeed_scu_ic_of_init );
294+ IRQCHIP_DECLARE (ast2700_scu_ic3 , "aspeed,ast2700-scu-ic3" , aspeed_scu_ic_of_init );
0 commit comments