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