2 * Support for Intel Camera Imaging ISP subsystem.
3 * Copyright (c) 2010-2015, Intel Corporation.
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.
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
15 #include "assert_support.h"
18 #ifndef __INLINE_GP_DEVICE__
19 #define __INLINE_GP_DEVICE__
21 #include "gp_device.h" /* _REG_GP_IRQ_REQUEST_ADDR */
23 #include "platform_support.h" /* hrt_sleep() */
25 STORAGE_CLASS_INLINE void irq_wait_for_write_complete(
28 STORAGE_CLASS_INLINE bool any_irq_channel_enabled(
31 STORAGE_CLASS_INLINE irq_ID_t virq_get_irq_id(
32 const virq_id_t irq_ID,
33 unsigned int *channel_ID);
35 #ifndef __INLINE_IRQ__
36 #include "irq_private.h"
37 #endif /* __INLINE_IRQ__ */
39 static unsigned short IRQ_N_CHANNEL[N_IRQ_ID] = {
45 static unsigned short IRQ_N_ID_OFFSET[N_IRQ_ID + 1] = {
52 static virq_id_t IRQ_NESTING_ID[N_IRQ_ID] = {
61 hrt_data mask = 0xFFFFFFFF;
63 assert(ID < N_IRQ_ID);
64 assert(IRQ_N_CHANNEL[ID] <= HRT_DATA_WIDTH);
66 if (IRQ_N_CHANNEL[ID] < HRT_DATA_WIDTH) {
67 mask = ~((~(hrt_data)0)>>IRQ_N_CHANNEL[ID]);
71 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, mask);
76 * Do we want the user to be able to set the signalling method ?
78 void irq_enable_channel(
80 const unsigned int irq_id)
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;
90 assert(ID < N_IRQ_ID);
91 assert(irq_id < IRQ_N_CHANNEL[ID]);
95 edge_in |= me; /* rising edge */
97 /* to avoid mishaps configuration must follow the following order */
99 /* mask this interrupt */
101 _HRT_IRQ_CONTROLLER_MASK_REG_IDX, mask & ~me);
102 /* rising edge at input */
104 _HRT_IRQ_CONTROLLER_EDGE_REG_IDX, edge_in);
105 /* enable interrupt to output */
107 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX, enable);
108 /* clear current irq only */
110 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, me);
111 /* unmask interrupt from input */
113 _HRT_IRQ_CONTROLLER_MASK_REG_IDX, mask);
115 irq_wait_for_write_complete(ID);
120 void irq_enable_pulse(
124 unsigned int edge_out = 0x0;
127 edge_out = 0xffffffff;
129 /* output is given as edge, not pulse */
131 _HRT_IRQ_CONTROLLER_EDGE_NOT_PULSE_REG_IDX, edge_out);
135 void irq_disable_channel(
137 const unsigned int irq_id)
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;
145 assert(ID < N_IRQ_ID);
146 assert(irq_id < IRQ_N_CHANNEL[ID]);
151 /* enable interrupt to output */
153 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX, enable);
154 /* unmask interrupt from input */
156 _HRT_IRQ_CONTROLLER_MASK_REG_IDX, mask);
157 /* clear current irq only */
159 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, me);
161 irq_wait_for_write_complete(ID);
166 enum hrt_isp_css_irq_status irq_get_channel_id(
168 unsigned int *irq_id)
170 unsigned int irq_status = irq_reg_load(ID,
171 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX);
173 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_success;
175 assert(ID < N_IRQ_ID);
176 assert(irq_id != NULL);
178 /* find the first irq bit */
179 for (idx = 0; idx < IRQ_N_CHANNEL[ID]; idx++) {
180 if (irq_status & (1U << idx))
183 if (idx == IRQ_N_CHANNEL[ID])
184 return hrt_isp_css_irq_status_error;
186 /* now check whether there are more bits set */
187 if (irq_status != (1U << idx))
188 status = hrt_isp_css_irq_status_more_irqs;
191 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, 1U << idx);
193 irq_wait_for_write_complete(ID);
196 *irq_id = (unsigned int)idx;
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};
207 const irq_sw_channel_id_t irq_id)
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);
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);
226 void irq_controller_get_state(
228 irq_controller_state_t *state)
230 assert(ID < N_IRQ_ID);
231 assert(state != NULL);
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);
246 bool any_virq_signal(void)
248 unsigned int irq_status = irq_reg_load(IRQ0_ID,
249 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX);
251 return (irq_status != 0);
254 void cnd_virq_enable_channel(
255 const virq_id_t irq_ID,
259 unsigned int channel_ID;
260 irq_ID_t ID = virq_get_irq_id(irq_ID, &channel_ID);
262 assert(ID < N_IRQ_ID);
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]);
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]);
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]);
286 void virq_clear_all(void)
290 for (irq_id = (irq_ID_t)0; irq_id < N_IRQ_ID; irq_id++) {
291 irq_clear_all(irq_id);
296 enum hrt_isp_css_irq_status virq_get_channel_signals(
297 virq_info_t *irq_info)
299 enum hrt_isp_css_irq_status irq_status = hrt_isp_css_irq_status_error;
302 assert(irq_info != NULL);
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);
310 /* The error condition is an IRQ pulse received with no IRQ status written */
311 irq_status = hrt_isp_css_irq_status_success;
314 irq_info->irq_status_reg[ID] |= irq_data;
317 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, irq_data);
319 irq_wait_for_write_complete(ID);
326 void virq_clear_info(
327 virq_info_t *irq_info)
331 assert(irq_info != NULL);
333 for (ID = (irq_ID_t)0 ; ID < N_IRQ_ID; ID++) {
334 irq_info->irq_status_reg[ID] = 0;
339 enum hrt_isp_css_irq_status virq_get_channel_id(
342 unsigned int irq_status = irq_reg_load(IRQ0_ID,
343 _HRT_IRQ_CONTROLLER_STATUS_REG_IDX);
345 enum hrt_isp_css_irq_status status = hrt_isp_css_irq_status_success;
348 assert(irq_id != NULL);
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))
356 if (idx == IRQ_N_CHANNEL[IRQ0_ID]) {
357 return hrt_isp_css_irq_status_error;
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;
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) {
372 /* If we have a nested IRQ, load that state, discard the device 0 state */
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))
382 if (idx == IRQ_N_CHANNEL[ID]) {
383 return hrt_isp_css_irq_status_error;
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;
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]);
394 } /* if (ID != IRQ0_ID) */
396 /* Here we proceed to clear the IRQ on detected device, if no nested IRQ, this is device 0 */
398 _HRT_IRQ_CONTROLLER_CLEAR_REG_IDX, 1U << idx);
400 irq_wait_for_write_complete(ID);
402 idx += IRQ_N_ID_OFFSET[ID];
404 *irq_id = (virq_id_t)idx;
409 STORAGE_CLASS_INLINE void irq_wait_for_write_complete(
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));
418 STORAGE_CLASS_INLINE bool any_irq_channel_enabled(
423 assert(ID < N_IRQ_ID);
425 en_reg = irq_reg_load(ID,
426 _HRT_IRQ_CONTROLLER_ENABLE_REG_IDX);
428 return (en_reg != 0);
431 STORAGE_CLASS_INLINE irq_ID_t virq_get_irq_id(
432 const virq_id_t irq_ID,
433 unsigned int *channel_ID)
437 assert(channel_ID != NULL);
439 for (ID = (irq_ID_t)0 ; ID < N_IRQ_ID; ID++) {
440 if (irq_ID < IRQ_N_ID_OFFSET[ID + 1]) {
445 *channel_ID = (unsigned int)irq_ID - IRQ_N_ID_OFFSET[ID];