33 * Copyright (C) 2024 Inochi Amaoto <inochiama@gmail.com>
44 */
55
6- #define pr_fmt (fmt ) "thead-c900-aclint-sswi: " fmt
6+ #define pr_fmt (fmt ) KBUILD_MODNAME ": " fmt
7+
78#include <linux/cpu.h>
89#include <linux/interrupt.h>
910#include <linux/io.h>
2122#include <asm/sbi.h>
2223#include <asm/vendorid_list.h>
2324
24- #define THEAD_ACLINT_xSWI_REGISTER_SIZE 4
25-
26- #define THEAD_C9XX_CSR_SXSTATUS 0x5c0
27- #define THEAD_C9XX_SXSTATUS_CLINTEE BIT(17)
28-
2925static int sswi_ipi_virq __ro_after_init ;
3026static DEFINE_PER_CPU (void __iomem * , sswi_cpu_regs ) ;
3127
32- static void thead_aclint_sswi_ipi_send (unsigned int cpu )
28+ static void aclint_sswi_ipi_send (unsigned int cpu )
3329{
3430 writel (0x1 , per_cpu (sswi_cpu_regs , cpu ));
3531}
3632
37- static void thead_aclint_sswi_ipi_clear (void )
33+ static void aclint_sswi_ipi_clear (void )
3834{
3935 writel_relaxed (0x0 , this_cpu_read (sswi_cpu_regs ));
4036}
4137
42- static void thead_aclint_sswi_ipi_handle (struct irq_desc * desc )
38+ static void aclint_sswi_ipi_handle (struct irq_desc * desc )
4339{
4440 struct irq_chip * chip = irq_desc_get_chip (desc );
4541
4642 chained_irq_enter (chip , desc );
4743
4844 csr_clear (CSR_IP , IE_SIE );
49- thead_aclint_sswi_ipi_clear ();
45+ aclint_sswi_ipi_clear ();
5046
5147 ipi_mux_process ();
5248
5349 chained_irq_exit (chip , desc );
5450}
5551
56- static int thead_aclint_sswi_starting_cpu (unsigned int cpu )
52+ static int aclint_sswi_starting_cpu (unsigned int cpu )
5753{
5854 enable_percpu_irq (sswi_ipi_virq , irq_get_trigger_type (sswi_ipi_virq ));
5955
6056 return 0 ;
6157}
6258
63- static int thead_aclint_sswi_dying_cpu (unsigned int cpu )
59+ static int aclint_sswi_dying_cpu (unsigned int cpu )
6460{
65- thead_aclint_sswi_ipi_clear ();
61+ aclint_sswi_ipi_clear ();
6662
6763 disable_percpu_irq (sswi_ipi_virq );
6864
6965 return 0 ;
7066}
7167
72- static int __init thead_aclint_sswi_parse_irq (struct fwnode_handle * fwnode ,
73- void __iomem * reg )
68+ static int __init aclint_sswi_parse_irq (struct fwnode_handle * fwnode , void __iomem * reg )
7469{
7570 struct of_phandle_args parent ;
7671 unsigned long hartid ;
@@ -97,25 +92,20 @@ static int __init thead_aclint_sswi_parse_irq(struct fwnode_handle *fwnode,
9792
9893 cpu = riscv_hartid_to_cpuid (hartid );
9994
100- per_cpu (sswi_cpu_regs , cpu ) = reg + i * THEAD_ACLINT_xSWI_REGISTER_SIZE ;
95+ per_cpu (sswi_cpu_regs , cpu ) = reg + hart_index * 4 ;
10196 }
10297
10398 pr_info ("%pfwP: register %u CPU%s\n" , fwnode , contexts , str_plural (contexts ));
10499
105100 return 0 ;
106101}
107102
108- static int __init thead_aclint_sswi_probe (struct fwnode_handle * fwnode )
103+ static int __init aclint_sswi_probe (struct fwnode_handle * fwnode )
109104{
110105 struct irq_domain * domain ;
111106 void __iomem * reg ;
112107 int virq , rc ;
113108
114- /* If it is T-HEAD CPU, check whether SSWI is enabled */
115- if (riscv_cached_mvendorid (0 ) == THEAD_VENDOR_ID &&
116- !(csr_read (THEAD_C9XX_CSR_SXSTATUS ) & THEAD_C9XX_SXSTATUS_CLINTEE ))
117- return - ENOTSUPP ;
118-
119109 if (!is_of_node (fwnode ))
120110 return - EINVAL ;
121111
@@ -124,7 +114,7 @@ static int __init thead_aclint_sswi_probe(struct fwnode_handle *fwnode)
124114 return - ENOMEM ;
125115
126116 /* Parse SSWI setting */
127- rc = thead_aclint_sswi_parse_irq (fwnode , reg );
117+ rc = aclint_sswi_parse_irq (fwnode , reg );
128118 if (rc < 0 )
129119 return rc ;
130120
@@ -146,22 +136,64 @@ static int __init thead_aclint_sswi_probe(struct fwnode_handle *fwnode)
146136 }
147137
148138 /* Register SSWI irq and handler */
149- virq = ipi_mux_create (BITS_PER_BYTE , thead_aclint_sswi_ipi_send );
139+ virq = ipi_mux_create (BITS_PER_BYTE , aclint_sswi_ipi_send );
150140 if (virq <= 0 ) {
151141 pr_err ("unable to create muxed IPIs\n" );
152142 irq_dispose_mapping (sswi_ipi_virq );
153143 return virq < 0 ? virq : - ENOMEM ;
154144 }
155145
156- irq_set_chained_handler (sswi_ipi_virq , thead_aclint_sswi_ipi_handle );
146+ irq_set_chained_handler (sswi_ipi_virq , aclint_sswi_ipi_handle );
157147
158- cpuhp_setup_state (CPUHP_AP_IRQ_THEAD_ACLINT_SSWI_STARTING ,
159- "irqchip/thead- aclint-sswi:starting" ,
160- thead_aclint_sswi_starting_cpu ,
161- thead_aclint_sswi_dying_cpu );
148+ cpuhp_setup_state (CPUHP_AP_IRQ_ACLINT_SSWI_STARTING ,
149+ "irqchip/aclint-sswi:starting" ,
150+ aclint_sswi_starting_cpu ,
151+ aclint_sswi_dying_cpu );
162152
163153 riscv_ipi_set_virq_range (virq , BITS_PER_BYTE );
164154
155+ return 0 ;
156+ }
157+
158+ /* generic/MIPS variant */
159+ static int __init generic_aclint_sswi_probe (struct fwnode_handle * fwnode )
160+ {
161+ int rc ;
162+
163+ rc = aclint_sswi_probe (fwnode );
164+ if (rc )
165+ return rc ;
166+
167+ /* Announce that SSWI is providing IPIs */
168+ pr_info ("providing IPIs using ACLINT SSWI\n" );
169+
170+ return 0 ;
171+ }
172+
173+ static int __init generic_aclint_sswi_early_probe (struct device_node * node ,
174+ struct device_node * parent )
175+ {
176+ return generic_aclint_sswi_probe (& node -> fwnode );
177+ }
178+ IRQCHIP_DECLARE (generic_aclint_sswi , "mips,p8700-aclint-sswi" , generic_aclint_sswi_early_probe );
179+
180+ /* THEAD variant */
181+ #define THEAD_C9XX_CSR_SXSTATUS 0x5c0
182+ #define THEAD_C9XX_SXSTATUS_CLINTEE BIT(17)
183+
184+ static int __init thead_aclint_sswi_probe (struct fwnode_handle * fwnode )
185+ {
186+ int rc ;
187+
188+ /* If it is T-HEAD CPU, check whether SSWI is enabled */
189+ if (riscv_cached_mvendorid (0 ) == THEAD_VENDOR_ID &&
190+ !(csr_read (THEAD_C9XX_CSR_SXSTATUS ) & THEAD_C9XX_SXSTATUS_CLINTEE ))
191+ return - ENOTSUPP ;
192+
193+ rc = aclint_sswi_probe (fwnode );
194+ if (rc )
195+ return rc ;
196+
165197 /* Announce that SSWI is providing IPIs */
166198 pr_info ("providing IPIs using THEAD ACLINT SSWI\n" );
167199
0 commit comments