@@ -85,10 +85,9 @@ static struct rzg2l_irqc_priv *irq_data_to_priv(struct irq_data *data)
85
85
return data -> domain -> host_data ;
86
86
}
87
87
88
- static void rzg2l_irq_eoi (struct irq_data * d )
88
+ static void rzg2l_clear_irq_int (struct rzg2l_irqc_priv * priv , unsigned int hwirq )
89
89
{
90
- unsigned int hw_irq = irqd_to_hwirq (d ) - IRQC_IRQ_START ;
91
- struct rzg2l_irqc_priv * priv = irq_data_to_priv (d );
90
+ unsigned int hw_irq = hwirq - IRQC_IRQ_START ;
92
91
u32 bit = BIT (hw_irq );
93
92
u32 iitsr , iscr ;
94
93
@@ -99,20 +98,30 @@ static void rzg2l_irq_eoi(struct irq_data *d)
99
98
* ISCR can only be cleared if the type is falling-edge, rising-edge or
100
99
* falling/rising-edge.
101
100
*/
102
- if ((iscr & bit ) && (iitsr & IITSR_IITSEL_MASK (hw_irq )))
101
+ if ((iscr & bit ) && (iitsr & IITSR_IITSEL_MASK (hw_irq ))) {
103
102
writel_relaxed (iscr & ~bit , priv -> base + ISCR );
103
+ /*
104
+ * Enforce that the posted write is flushed to prevent that the
105
+ * just handled interrupt is raised again.
106
+ */
107
+ readl_relaxed (priv -> base + ISCR );
108
+ }
104
109
}
105
110
106
- static void rzg2l_tint_eoi (struct irq_data * d )
111
+ static void rzg2l_clear_tint_int (struct rzg2l_irqc_priv * priv , unsigned int hwirq )
107
112
{
108
- unsigned int hw_irq = irqd_to_hwirq (d ) - IRQC_TINT_START ;
109
- struct rzg2l_irqc_priv * priv = irq_data_to_priv (d );
110
- u32 bit = BIT (hw_irq );
113
+ u32 bit = BIT (hwirq - IRQC_TINT_START );
111
114
u32 reg ;
112
115
113
116
reg = readl_relaxed (priv -> base + TSCR );
114
- if (reg & bit )
117
+ if (reg & bit ) {
115
118
writel_relaxed (reg & ~bit , priv -> base + TSCR );
119
+ /*
120
+ * Enforce that the posted write is flushed to prevent that the
121
+ * just handled interrupt is raised again.
122
+ */
123
+ readl_relaxed (priv -> base + TSCR );
124
+ }
116
125
}
117
126
118
127
static void rzg2l_irqc_eoi (struct irq_data * d )
@@ -122,9 +131,9 @@ static void rzg2l_irqc_eoi(struct irq_data *d)
122
131
123
132
raw_spin_lock (& priv -> lock );
124
133
if (hw_irq >= IRQC_IRQ_START && hw_irq <= IRQC_IRQ_COUNT )
125
- rzg2l_irq_eoi ( d );
134
+ rzg2l_clear_irq_int ( priv , hw_irq );
126
135
else if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ )
127
- rzg2l_tint_eoi ( d );
136
+ rzg2l_clear_tint_int ( priv , hw_irq );
128
137
raw_spin_unlock (& priv -> lock );
129
138
irq_chip_eoi_parent (d );
130
139
}
@@ -142,7 +151,7 @@ static void rzg2l_irqc_irq_disable(struct irq_data *d)
142
151
143
152
raw_spin_lock (& priv -> lock );
144
153
reg = readl_relaxed (priv -> base + TSSR (tssr_index ));
145
- reg &= ~(TSSEL_MASK << TSSEL_SHIFT (tssr_offset ));
154
+ reg &= ~(TIEN << TSSEL_SHIFT (tssr_offset ));
146
155
writel_relaxed (reg , priv -> base + TSSR (tssr_index ));
147
156
raw_spin_unlock (& priv -> lock );
148
157
}
@@ -154,7 +163,6 @@ static void rzg2l_irqc_irq_enable(struct irq_data *d)
154
163
unsigned int hw_irq = irqd_to_hwirq (d );
155
164
156
165
if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ ) {
157
- unsigned long tint = (uintptr_t )irq_data_get_irq_chip_data (d );
158
166
struct rzg2l_irqc_priv * priv = irq_data_to_priv (d );
159
167
u32 offset = hw_irq - IRQC_TINT_START ;
160
168
u32 tssr_offset = TSSR_OFFSET (offset );
@@ -163,7 +171,7 @@ static void rzg2l_irqc_irq_enable(struct irq_data *d)
163
171
164
172
raw_spin_lock (& priv -> lock );
165
173
reg = readl_relaxed (priv -> base + TSSR (tssr_index ));
166
- reg |= ( TIEN | tint ) << TSSEL_SHIFT (tssr_offset );
174
+ reg |= TIEN << TSSEL_SHIFT (tssr_offset );
167
175
writel_relaxed (reg , priv -> base + TSSR (tssr_index ));
168
176
raw_spin_unlock (& priv -> lock );
169
177
}
@@ -172,8 +180,10 @@ static void rzg2l_irqc_irq_enable(struct irq_data *d)
172
180
173
181
static int rzg2l_irq_set_type (struct irq_data * d , unsigned int type )
174
182
{
175
- unsigned int hw_irq = irqd_to_hwirq (d ) - IRQC_IRQ_START ;
176
183
struct rzg2l_irqc_priv * priv = irq_data_to_priv (d );
184
+ unsigned int hwirq = irqd_to_hwirq (d );
185
+ u32 iitseln = hwirq - IRQC_IRQ_START ;
186
+ bool clear_irq_int = false;
177
187
u16 sense , tmp ;
178
188
179
189
switch (type & IRQ_TYPE_SENSE_MASK ) {
@@ -183,14 +193,17 @@ static int rzg2l_irq_set_type(struct irq_data *d, unsigned int type)
183
193
184
194
case IRQ_TYPE_EDGE_FALLING :
185
195
sense = IITSR_IITSEL_EDGE_FALLING ;
196
+ clear_irq_int = true;
186
197
break ;
187
198
188
199
case IRQ_TYPE_EDGE_RISING :
189
200
sense = IITSR_IITSEL_EDGE_RISING ;
201
+ clear_irq_int = true;
190
202
break ;
191
203
192
204
case IRQ_TYPE_EDGE_BOTH :
193
205
sense = IITSR_IITSEL_EDGE_BOTH ;
206
+ clear_irq_int = true;
194
207
break ;
195
208
196
209
default :
@@ -199,21 +212,40 @@ static int rzg2l_irq_set_type(struct irq_data *d, unsigned int type)
199
212
200
213
raw_spin_lock (& priv -> lock );
201
214
tmp = readl_relaxed (priv -> base + IITSR );
202
- tmp &= ~IITSR_IITSEL_MASK (hw_irq );
203
- tmp |= IITSR_IITSEL (hw_irq , sense );
215
+ tmp &= ~IITSR_IITSEL_MASK (iitseln );
216
+ tmp |= IITSR_IITSEL (iitseln , sense );
217
+ if (clear_irq_int )
218
+ rzg2l_clear_irq_int (priv , hwirq );
204
219
writel_relaxed (tmp , priv -> base + IITSR );
205
220
raw_spin_unlock (& priv -> lock );
206
221
207
222
return 0 ;
208
223
}
209
224
225
+ static u32 rzg2l_disable_tint_and_set_tint_source (struct irq_data * d , struct rzg2l_irqc_priv * priv ,
226
+ u32 reg , u32 tssr_offset , u8 tssr_index )
227
+ {
228
+ u32 tint = (u32 )(uintptr_t )irq_data_get_irq_chip_data (d );
229
+ u32 tien = reg & (TIEN << TSSEL_SHIFT (tssr_offset ));
230
+
231
+ /* Clear the relevant byte in reg */
232
+ reg &= ~(TSSEL_MASK << TSSEL_SHIFT (tssr_offset ));
233
+ /* Set TINT and leave TIEN clear */
234
+ reg |= tint << TSSEL_SHIFT (tssr_offset );
235
+ writel_relaxed (reg , priv -> base + TSSR (tssr_index ));
236
+
237
+ return reg | tien ;
238
+ }
239
+
210
240
static int rzg2l_tint_set_edge (struct irq_data * d , unsigned int type )
211
241
{
212
242
struct rzg2l_irqc_priv * priv = irq_data_to_priv (d );
213
243
unsigned int hwirq = irqd_to_hwirq (d );
214
244
u32 titseln = hwirq - IRQC_TINT_START ;
245
+ u32 tssr_offset = TSSR_OFFSET (titseln );
246
+ u8 tssr_index = TSSR_INDEX (titseln );
215
247
u8 index , sense ;
216
- u32 reg ;
248
+ u32 reg , tssr ;
217
249
218
250
switch (type & IRQ_TYPE_SENSE_MASK ) {
219
251
case IRQ_TYPE_EDGE_RISING :
@@ -235,10 +267,14 @@ static int rzg2l_tint_set_edge(struct irq_data *d, unsigned int type)
235
267
}
236
268
237
269
raw_spin_lock (& priv -> lock );
270
+ tssr = readl_relaxed (priv -> base + TSSR (tssr_index ));
271
+ tssr = rzg2l_disable_tint_and_set_tint_source (d , priv , tssr , tssr_offset , tssr_index );
238
272
reg = readl_relaxed (priv -> base + TITSR (index ));
239
273
reg &= ~(IRQ_MASK << (titseln * TITSEL_WIDTH ));
240
274
reg |= sense << (titseln * TITSEL_WIDTH );
241
275
writel_relaxed (reg , priv -> base + TITSR (index ));
276
+ rzg2l_clear_tint_int (priv , hwirq );
277
+ writel_relaxed (tssr , priv -> base + TSSR (tssr_index ));
242
278
raw_spin_unlock (& priv -> lock );
243
279
244
280
return 0 ;
0 commit comments