1717
1818static char smp_cpuinfo_buf [128 ];
1919
20- /*-------------------------------------------------------------------
20+ /*
21+ *-------------------------------------------------------------------
2122 * Platform specific callbacks expected by arch SMP code
2223 *-------------------------------------------------------------------
2324 */
@@ -56,25 +57,44 @@ void arc_platform_smp_wakeup_cpu(int cpu, unsigned long pc)
5657}
5758
5859/*
59- * Any SMP specific init CPU does when it comes up
60- * Called from start_kernel_secondary()
60+ * Any SMP specific init any CPU does when it comes up.
61+ * Here we setup the CPU to enable Inter-Processor-Interrupts
62+ * Called for each CPU
63+ * -Master : init_IRQ()
64+ * -Other(s) : start_kernel_secondary()
6165 */
6266void arc_platform_smp_init_cpu (void )
6367{
64- /* Owner of the Idu Interrupt determines who is SELF */
6568 int cpu = smp_processor_id ();
6669
6770 /* Check if CPU is configured for more than 16 interrupts */
6871 if (NR_IRQS <= 16 || get_hw_config_num_irq () <= 16 )
6972 panic ("[arcfpga] IRQ system can't support IDU IPI\n" );
7073
71- /* Setup the interrupt in IDU */
7274 idu_disable ();
7375
74- idu_irq_set_tgtcpu (cpu , /* IDU IRQ assoc with CPU */
75- (0x1 << cpu ) /* target cpus mask, here single cpu */
76- );
77-
76+ /****************************************************************
77+ * IDU provides a set of Common IRQs, each of which can be dynamically
78+ * attached to (1|many|all) CPUs.
79+ * The Common IRQs [0-15] are mapped as CPU pvt [16-31]
80+ *
81+ * Here we use a simple 1:1 mapping:
82+ * A CPU 'x' is wired to Common IRQ 'x'.
83+ * So an IDU ASSERT on IRQ 'x' will trigger Interupt on CPU 'x', which
84+ * makes up for our simple IPI plumbing.
85+ *
86+ * TBD: Have a dedicated multicast IRQ for sending IPIs to all CPUs
87+ * w/o having to do one-at-a-time
88+ ******************************************************************/
89+
90+ /*
91+ * Claim an IRQ which would trigger IPI on this CPU.
92+ * In IDU parlance it involves setting up a cpu bitmask for the IRQ
93+ * The bitmap here contains only 1 CPU (self).
94+ */
95+ idu_irq_set_tgtcpu (cpu , 0x1 << cpu );
96+
97+ /* Set the IRQ destination to use the bitmask above */
7898 idu_irq_set_mode (cpu , 7 , /* XXX: IDU_IRQ_MOD_TCPU_ALLRECP: ISS bug */
7999 IDU_IRQ_MODE_PULSE_TRIG );
80100
@@ -97,11 +117,13 @@ void arc_platform_ipi_clear(int cpu, int irq)
97117 idu_irq_clear (IDU_INTERRUPT_0 + cpu );
98118}
99119
100- /*-------------------------------------------------------------------
101- * IDU helpers
120+ /*
121+ *-------------------------------------------------------------------
122+ * Low level Platform IPI Providers
102123 *-------------------------------------------------------------------
103124 */
104125
126+ /* Set the Mode for the Common IRQ */
105127void idu_irq_set_mode (uint8_t irq , uint8_t dest_mode , uint8_t trig_mode )
106128{
107129 uint32_t par = IDU_IRQ_MODE_PARAM (dest_mode , trig_mode );
@@ -110,12 +132,14 @@ void idu_irq_set_mode(uint8_t irq, uint8_t dest_mode, uint8_t trig_mode)
110132 IDU_SET_COMMAND (irq , IDU_IRQ_WMODE );
111133}
112134
135+ /* Set the target cpu Bitmask for Common IRQ */
113136void idu_irq_set_tgtcpu (uint8_t irq , uint32_t mask )
114137{
115138 IDU_SET_PARAM (mask );
116139 IDU_SET_COMMAND (irq , IDU_IRQ_WBITMASK );
117140}
118141
142+ /* Get the Interrupt Acknowledged status for IRQ (as CPU Bitmask) */
119143bool idu_irq_get_ack (uint8_t irq )
120144{
121145 uint32_t val ;
@@ -126,6 +150,12 @@ bool idu_irq_get_ack(uint8_t irq)
126150 return val & (1 << irq );
127151}
128152
153+ /*
154+ * Get the Interrupt Pending status for IRQ (as CPU Bitmask)
155+ * -Pending means CPU has not yet noticed the IRQ (e.g. disabled)
156+ * -After Interrupt has been taken, the IPI expcitily needs to be
157+ * cleared, to be acknowledged.
158+ */
129159bool idu_irq_get_pend (uint8_t irq )
130160{
131161 uint32_t val ;
0 commit comments