17
17
18
18
static char smp_cpuinfo_buf [128 ];
19
19
20
- /*-------------------------------------------------------------------
20
+ /*
21
+ *-------------------------------------------------------------------
21
22
* Platform specific callbacks expected by arch SMP code
22
23
*-------------------------------------------------------------------
23
24
*/
@@ -56,25 +57,44 @@ void arc_platform_smp_wakeup_cpu(int cpu, unsigned long pc)
56
57
}
57
58
58
59
/*
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()
61
65
*/
62
66
void arc_platform_smp_init_cpu (void )
63
67
{
64
- /* Owner of the Idu Interrupt determines who is SELF */
65
68
int cpu = smp_processor_id ();
66
69
67
70
/* Check if CPU is configured for more than 16 interrupts */
68
71
if (NR_IRQS <= 16 || get_hw_config_num_irq () <= 16 )
69
72
panic ("[arcfpga] IRQ system can't support IDU IPI\n" );
70
73
71
- /* Setup the interrupt in IDU */
72
74
idu_disable ();
73
75
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 */
78
98
idu_irq_set_mode (cpu , 7 , /* XXX: IDU_IRQ_MOD_TCPU_ALLRECP: ISS bug */
79
99
IDU_IRQ_MODE_PULSE_TRIG );
80
100
@@ -97,11 +117,13 @@ void arc_platform_ipi_clear(int cpu, int irq)
97
117
idu_irq_clear (IDU_INTERRUPT_0 + cpu );
98
118
}
99
119
100
- /*-------------------------------------------------------------------
101
- * IDU helpers
120
+ /*
121
+ *-------------------------------------------------------------------
122
+ * Low level Platform IPI Providers
102
123
*-------------------------------------------------------------------
103
124
*/
104
125
126
+ /* Set the Mode for the Common IRQ */
105
127
void idu_irq_set_mode (uint8_t irq , uint8_t dest_mode , uint8_t trig_mode )
106
128
{
107
129
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)
110
132
IDU_SET_COMMAND (irq , IDU_IRQ_WMODE );
111
133
}
112
134
135
+ /* Set the target cpu Bitmask for Common IRQ */
113
136
void idu_irq_set_tgtcpu (uint8_t irq , uint32_t mask )
114
137
{
115
138
IDU_SET_PARAM (mask );
116
139
IDU_SET_COMMAND (irq , IDU_IRQ_WBITMASK );
117
140
}
118
141
142
+ /* Get the Interrupt Acknowledged status for IRQ (as CPU Bitmask) */
119
143
bool idu_irq_get_ack (uint8_t irq )
120
144
{
121
145
uint32_t val ;
@@ -126,6 +150,12 @@ bool idu_irq_get_ack(uint8_t irq)
126
150
return val & (1 << irq );
127
151
}
128
152
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
+ */
129
159
bool idu_irq_get_pend (uint8_t irq )
130
160
{
131
161
uint32_t val ;
0 commit comments