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