1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Support for Intel Camera Imaging ISP subsystem.
4 * Copyright (c) 2010-2015, Intel Corporation.
5 */
6
7 #include "assert_support.h"
8 #include "irq.h"
9
10 #ifndef __INLINE_GP_DEVICE__
11 #define __INLINE_GP_DEVICE__
12 #endif
13 #include "gp_device.h" /* _REG_GP_IRQ_REQUEST_ADDR */
14
15 static inline void irq_wait_for_write_complete(
16 const irq_ID_t ID);
17
18 static inline bool any_irq_channel_enabled(
19 const irq_ID_t ID);
20
21 static inline irq_ID_t virq_get_irq_id(const enum virq_id irq_ID,
22 unsigned int *channel_ID);
23
24 #ifndef __INLINE_IRQ__
25 #include "irq_private.h"
26 #endif /* __INLINE_IRQ__ */
27
28 static unsigned short IRQ_N_CHANNEL[N_IRQ_ID] = {
29 IRQ0_ID_N_CHANNEL,
30 IRQ1_ID_N_CHANNEL,
31 IRQ2_ID_N_CHANNEL,
32 IRQ3_ID_N_CHANNEL
33 };
34
35 static unsigned short IRQ_N_ID_OFFSET[N_IRQ_ID + 1] = {
36 IRQ0_ID_OFFSET,
37 IRQ1_ID_OFFSET,
38 IRQ2_ID_OFFSET,
39 IRQ3_ID_OFFSET,
40 IRQ_END_OFFSET
41 };
42
43 static enum virq_id IRQ_NESTING_ID[N_IRQ_ID] = {
44 N_virq_id,
45 virq_ifmt,
46 virq_isys,
47 virq_isel
48 };
49
irq_clear_all(const irq_ID_t ID)50 void irq_clear_all(
51 const irq_ID_t ID)
52 {
53 hrt_data mask = 0xFFFFFFFF;
54
55 assert(ID < N_IRQ_ID);
56 assert(IRQ_N_CHANNEL[ID] <= HRT_DATA_WIDTH);
57
58 if (IRQ_N_CHANNEL[ID] < HRT_DATA_WIDTH) {
59 mask = ~((~(hrt_data)0) >> IRQ_N_CHANNEL[ID]);
60 }
61
62 irq_reg_store(ID,
63 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, mask);
64 return;
65 }
66
67 /*
68 * Do we want the user to be able to set the signalling method ?
69 */
irq_enable_channel(const irq_ID_t ID,const unsigned int irq_id)70 void irq_enable_channel(
71 const irq_ID_t ID,
72 const unsigned int irq_id)
73 {
74 unsigned int mask = irq_reg_load(ID,
75 _HRT_IRQ_CONTROLLER_MASK_REG_IDX);
76 unsigned int enable = irq_reg_load(ID,
77 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX);
78 unsigned int edge_in = irq_reg_load(ID,
79 _HRT_IRQ_CONTROLLER_EDGE_REG_IDX);
80 unsigned int me = 1U << irq_id;
81
82 assert(ID < N_IRQ_ID);
83 assert(irq_id < IRQ_N_CHANNEL[ID]);
84
85 mask |= me;
86 enable |= me;
87 edge_in |= me; /* rising edge */
88
89 /* to avoid mishaps configuration must follow the following order */
90
91 /* mask this interrupt */
92 irq_reg_store(ID,
93 _HRT_IRQ_CONTROLLER_MASK_REG_IDX, mask & ~me);
94 /* rising edge at input */
95 irq_reg_store(ID,
96 _HRT_IRQ_CONTROLLER_EDGE_REG_IDX, edge_in);
97 /* enable interrupt to output */
98 irq_reg_store(ID,
99 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX, enable);
100 /* clear current irq only */
101 irq_reg_store(ID,
102 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, me);
103 /* unmask interrupt from input */
104 irq_reg_store(ID,
105 _HRT_IRQ_CONTROLLER_MASK_REG_IDX, mask);
106
107 irq_wait_for_write_complete(ID);
108
109 return;
110 }
111
irq_enable_pulse(const irq_ID_t ID,bool pulse)112 void irq_enable_pulse(
113 const irq_ID_t ID,
114 bool pulse)
115 {
116 unsigned int edge_out = 0x0;
117
118 if (pulse) {
119 edge_out = 0xffffffff;
120 }
121 /* output is given as edge, not pulse */
122 irq_reg_store(ID,
123 _HRT_IRQ_CONTROLLER_EDGE_NOT_PULSE_REG_IDX, edge_out);
124 return;
125 }
126
irq_disable_channel(const irq_ID_t ID,const unsigned int irq_id)127 void irq_disable_channel(
128 const irq_ID_t ID,
129 const unsigned int irq_id)
130 {
131 unsigned int mask = irq_reg_load(ID,
132 _HRT_IRQ_CONTROLLER_MASK_REG_IDX);
133 unsigned int enable = irq_reg_load(ID,
134 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX);
135 unsigned int me = 1U << irq_id;
136
137 assert(ID < N_IRQ_ID);
138 assert(irq_id < IRQ_N_CHANNEL[ID]);
139
140 mask &= ~me;
141 enable &= ~me;
142
143 /* enable interrupt to output */
144 irq_reg_store(ID,
145 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX, enable);
146 /* unmask interrupt from input */
147 irq_reg_store(ID,
148 _HRT_IRQ_CONTROLLER_MASK_REG_IDX, mask);
149 /* clear current irq only */
150 irq_reg_store(ID,
151 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, me);
152
153 irq_wait_for_write_complete(ID);
154
155 return;
156 }
157
irq_get_channel_id(const irq_ID_t ID,unsigned int * irq_id)158 enum hrt_isp_css_irq_status irq_get_channel_id(
159 const irq_ID_t ID,
160 unsigned int *irq_id)
161 {
162 unsigned int irq_status = irq_reg_load(ID,
163 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX);
164 unsigned int idx;
165 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_success;
166
167 assert(ID < N_IRQ_ID);
168 assert(irq_id);
169
170 /* find the first irq bit */
171 for (idx = 0; idx < IRQ_N_CHANNEL[ID]; idx++) {
172 if (irq_status & (1U << idx))
173 break;
174 }
175 if (idx == IRQ_N_CHANNEL[ID])
176 return hrt_isp_css_irq_status_error;
177
178 /* now check whether there are more bits set */
179 if (irq_status != (1U << idx))
180 status = hrt_isp_css_irq_status_more_irqs;
181
182 irq_reg_store(ID,
183 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, 1U << idx);
184
185 irq_wait_for_write_complete(ID);
186
187 if (irq_id)
188 *irq_id = (unsigned int)idx;
189
190 return status;
191 }
192
193 static const hrt_address IRQ_REQUEST_ADDR[N_IRQ_SW_CHANNEL_ID] = {
194 _REG_GP_IRQ_REQUEST0_ADDR,
195 _REG_GP_IRQ_REQUEST1_ADDR
196 };
197
irq_raise(const irq_ID_t ID,const irq_sw_channel_id_t irq_id)198 void irq_raise(
199 const irq_ID_t ID,
200 const irq_sw_channel_id_t irq_id)
201 {
202 hrt_address addr;
203
204 OP___assert(ID == IRQ0_ID);
205 OP___assert(IRQ_BASE[ID] != (hrt_address)-1);
206 OP___assert(irq_id < N_IRQ_SW_CHANNEL_ID);
207
208 (void)ID;
209
210 addr = IRQ_REQUEST_ADDR[irq_id];
211 /* The SW IRQ pins are remapped to offset zero */
212 gp_device_reg_store(GP_DEVICE0_ID,
213 (unsigned int)addr, 1);
214 gp_device_reg_store(GP_DEVICE0_ID,
215 (unsigned int)addr, 0);
216 return;
217 }
218
any_virq_signal(void)219 bool any_virq_signal(void)
220 {
221 unsigned int irq_status = irq_reg_load(IRQ0_ID,
222 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX);
223
224 return (irq_status != 0);
225 }
226
cnd_virq_enable_channel(const enum virq_id irq_ID,const bool en)227 void cnd_virq_enable_channel(
228 const enum virq_id irq_ID,
229 const bool en)
230 {
231 irq_ID_t i;
232 unsigned int channel_ID;
233 irq_ID_t ID = virq_get_irq_id(irq_ID, &channel_ID);
234
235 assert(ID < N_IRQ_ID);
236
237 for (i = IRQ1_ID; i < N_IRQ_ID; i++) {
238 /* It is not allowed to enable the pin of a nested IRQ directly */
239 assert(irq_ID != IRQ_NESTING_ID[i]);
240 }
241
242 if (en) {
243 irq_enable_channel(ID, channel_ID);
244 if (IRQ_NESTING_ID[ID] != N_virq_id) {
245 /* Single level nesting, otherwise we'd need to recurse */
246 irq_enable_channel(IRQ0_ID, IRQ_NESTING_ID[ID]);
247 }
248 } else {
249 irq_disable_channel(ID, channel_ID);
250 if ((IRQ_NESTING_ID[ID] != N_virq_id) && !any_irq_channel_enabled(ID)) {
251 /* Only disable the top if the nested ones are empty */
252 irq_disable_channel(IRQ0_ID, IRQ_NESTING_ID[ID]);
253 }
254 }
255 return;
256 }
257
virq_clear_all(void)258 void virq_clear_all(void)
259 {
260 irq_ID_t irq_id;
261
262 for (irq_id = (irq_ID_t)0; irq_id < N_IRQ_ID; irq_id++) {
263 irq_clear_all(irq_id);
264 }
265 return;
266 }
267
268 enum hrt_isp_css_irq_status
virq_get_channel_signals(struct virq_info * irq_info)269 virq_get_channel_signals(struct virq_info *irq_info)
270 {
271 enum hrt_isp_css_irq_status irq_status = hrt_isp_css_irq_status_error;
272 irq_ID_t ID;
273
274 assert(irq_info);
275
276 for (ID = (irq_ID_t)0 ; ID < N_IRQ_ID; ID++) {
277 if (any_irq_channel_enabled(ID)) {
278 hrt_data irq_data = irq_reg_load(ID,
279 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX);
280
281 if (irq_data != 0) {
282 /* The error condition is an IRQ pulse received with no IRQ status written */
283 irq_status = hrt_isp_css_irq_status_success;
284 }
285
286 irq_info->irq_status_reg[ID] |= irq_data;
287
288 irq_reg_store(ID,
289 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, irq_data);
290
291 irq_wait_for_write_complete(ID);
292 }
293 }
294
295 return irq_status;
296 }
297
virq_clear_info(struct virq_info * irq_info)298 void virq_clear_info(struct virq_info *irq_info)
299 {
300 irq_ID_t ID;
301
302 assert(irq_info);
303
304 for (ID = (irq_ID_t)0 ; ID < N_IRQ_ID; ID++) {
305 irq_info->irq_status_reg[ID] = 0;
306 }
307 return;
308 }
309
virq_get_channel_id(enum virq_id * irq_id)310 enum hrt_isp_css_irq_status virq_get_channel_id(
311 enum virq_id *irq_id)
312 {
313 unsigned int irq_status = irq_reg_load(IRQ0_ID,
314 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX);
315 unsigned int idx;
316 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_success;
317 irq_ID_t ID;
318
319 assert(irq_id);
320
321 /* find the first irq bit on device 0 */
322 for (idx = 0; idx < IRQ_N_CHANNEL[IRQ0_ID]; idx++) {
323 if (irq_status & (1U << idx))
324 break;
325 }
326
327 if (idx == IRQ_N_CHANNEL[IRQ0_ID]) {
328 return hrt_isp_css_irq_status_error;
329 }
330
331 /* Check whether there are more bits set on device 0 */
332 if (irq_status != (1U << idx)) {
333 status = hrt_isp_css_irq_status_more_irqs;
334 }
335
336 /* Check whether we have an IRQ on one of the nested devices */
337 for (ID = N_IRQ_ID - 1 ; ID > (irq_ID_t)0; ID--) {
338 if (IRQ_NESTING_ID[ID] == (enum virq_id)idx) {
339 break;
340 }
341 }
342
343 /* If we have a nested IRQ, load that state, discard the device 0 state */
344 if (ID != IRQ0_ID) {
345 irq_status = irq_reg_load(ID,
346 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX);
347 /* find the first irq bit on device "id" */
348 for (idx = 0; idx < IRQ_N_CHANNEL[ID]; idx++) {
349 if (irq_status & (1U << idx))
350 break;
351 }
352
353 if (idx == IRQ_N_CHANNEL[ID]) {
354 return hrt_isp_css_irq_status_error;
355 }
356
357 /* Alternatively check whether there are more bits set on this device */
358 if (irq_status != (1U << idx)) {
359 status = hrt_isp_css_irq_status_more_irqs;
360 } else {
361 /* If this device is empty, clear the state on device 0 */
362 irq_reg_store(IRQ0_ID,
363 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, 1U << IRQ_NESTING_ID[ID]);
364 }
365 } /* if (ID != IRQ0_ID) */
366
367 /* Here we proceed to clear the IRQ on detected device, if no nested IRQ, this is device 0 */
368 irq_reg_store(ID,
369 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, 1U << idx);
370
371 irq_wait_for_write_complete(ID);
372
373 idx += IRQ_N_ID_OFFSET[ID];
374 if (irq_id)
375 *irq_id = (enum virq_id)idx;
376
377 return status;
378 }
379
irq_wait_for_write_complete(const irq_ID_t ID)380 static inline void irq_wait_for_write_complete(
381 const irq_ID_t ID)
382 {
383 assert(ID < N_IRQ_ID);
384 assert(IRQ_BASE[ID] != (hrt_address)-1);
385 (void)ia_css_device_load_uint32(IRQ_BASE[ID] +
386 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX * sizeof(hrt_data));
387 }
388
any_irq_channel_enabled(const irq_ID_t ID)389 static inline bool any_irq_channel_enabled(
390 const irq_ID_t ID)
391 {
392 hrt_data en_reg;
393
394 assert(ID < N_IRQ_ID);
395
396 en_reg = irq_reg_load(ID,
397 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX);
398
399 return (en_reg != 0);
400 }
401
virq_get_irq_id(const enum virq_id irq_ID,unsigned int * channel_ID)402 static inline irq_ID_t virq_get_irq_id(
403 const enum virq_id irq_ID,
404 unsigned int *channel_ID)
405 {
406 irq_ID_t ID;
407
408 assert(channel_ID);
409
410 for (ID = (irq_ID_t)0 ; ID < N_IRQ_ID; ID++) {
411 if (irq_ID < IRQ_N_ID_OFFSET[ID + 1]) {
412 break;
413 }
414 }
415
416 *channel_ID = (unsigned int)irq_ID - IRQ_N_ID_OFFSET[ID];
417
418 return ID;
419 }
420