2 * This confidential and proprietary software may be used only as
3 * authorised by a licensing agreement from ARM Limited
4 * (C) COPYRIGHT 2008-2013 ARM Limited
6 * The entire notice above must be reproduced on all authorised
7 * copies and copies may only be made to the extent permitted
8 * by a licensing agreement from ARM Limited.
12 * @file mali_osk_irq.c
13 * Implementation of the OS abstraction layer for the kernel device driver
16 #include <linux/slab.h> /* For memory allocation */
17 #include <linux/interrupt.h>
18 #include <linux/wait.h>
19 #include <linux/sched.h>
22 #include "mali_kernel_common.h"
24 typedef struct _mali_osk_irq_t_struct
{
27 _mali_osk_irq_uhandler_t uhandler
;
28 } mali_osk_irq_object_t
;
30 typedef irqreturn_t (*irq_handler_func_t
)(int, void *, struct pt_regs
*);
31 static irqreturn_t
irq_handler_upper_half (int port_name
, void* dev_id
); /* , struct pt_regs *regs*/
36 struct test_interrupt_data
{
37 _mali_osk_irq_ack_t ack_func
;
39 mali_bool interrupt_received
;
43 static irqreturn_t
test_interrupt_upper_half(int port_name
, void *dev_id
)
45 irqreturn_t ret
= IRQ_NONE
;
46 struct test_interrupt_data
*data
= (struct test_interrupt_data
*)dev_id
;
48 if (_MALI_OSK_ERR_OK
== data
->ack_func(data
->probe_data
)) {
49 data
->interrupt_received
= MALI_TRUE
;
57 static _mali_osk_errcode_t
test_interrupt(u32 irqnum
,
58 _mali_osk_irq_trigger_t trigger_func
,
59 _mali_osk_irq_ack_t ack_func
,
61 const char *description
)
63 unsigned long irq_flags
= 0;
64 struct test_interrupt_data data
= {
66 .probe_data
= probe_data
,
67 .interrupt_received
= MALI_FALSE
,
70 #if defined(CONFIG_MALI_SHARED_INTERRUPTS)
71 irq_flags
|= IRQF_SHARED
;
72 #endif /* defined(CONFIG_MALI_SHARED_INTERRUPTS) */
74 if (0 != request_irq(irqnum
, test_interrupt_upper_half
, irq_flags
, description
, &data
)) {
75 MALI_DEBUG_PRINT(2, ("Unable to install test IRQ handler for core '%s'\n", description
));
76 return _MALI_OSK_ERR_FAULT
;
79 init_waitqueue_head(&data
.wq
);
81 trigger_func(probe_data
);
82 wait_event_timeout(data
.wq
, data
.interrupt_received
, 100);
84 free_irq(irqnum
, &data
);
86 if (data
.interrupt_received
) {
87 MALI_DEBUG_PRINT(3, ("%s: Interrupt test OK\n", description
));
88 return _MALI_OSK_ERR_OK
;
90 MALI_PRINT_ERROR(("%s: Failed interrupt test on %u\n", description
, irqnum
));
91 return _MALI_OSK_ERR_FAULT
;
96 #endif /* defined(DEBUG) */
98 _mali_osk_irq_t
*_mali_osk_irq_init( u32 irqnum
, _mali_osk_irq_uhandler_t uhandler
, void *int_data
, _mali_osk_irq_trigger_t trigger_func
, _mali_osk_irq_ack_t ack_func
, void *probe_data
, const char *description
)
100 mali_osk_irq_object_t
*irq_object
;
101 unsigned long irq_flags
= 0;
103 #if defined(CONFIG_MALI_SHARED_INTERRUPTS)
104 irq_flags
|= IRQF_SHARED
;
105 #endif /* defined(CONFIG_MALI_SHARED_INTERRUPTS) */
107 irq_object
= kmalloc(sizeof(mali_osk_irq_object_t
), GFP_KERNEL
);
108 if (NULL
== irq_object
) {
114 if ( (NULL
!= trigger_func
) && (NULL
!= ack_func
) ) {
115 unsigned long probe_count
= 3;
116 _mali_osk_errcode_t err
;
119 MALI_DEBUG_PRINT(2, ("Probing for irq\n"));
124 mask
= probe_irq_on();
125 trigger_func(probe_data
);
127 _mali_osk_time_ubusydelay(5);
129 irq
= probe_irq_off(mask
);
130 err
= ack_func(probe_data
);
131 } while (irq
< 0 && (err
== _MALI_OSK_ERR_OK
) && probe_count
--);
133 if (irq
< 0 || (_MALI_OSK_ERR_OK
!= err
)) irqnum
= -1;
135 } else irqnum
= -1; /* no probe functions, fault */
139 MALI_DEBUG_PRINT(2, ("Found irq %d\n", irqnum
));
141 MALI_DEBUG_PRINT(2, ("Probe for irq failed\n"));
145 irq_object
->irqnum
= irqnum
;
146 irq_object
->uhandler
= uhandler
;
147 irq_object
->data
= int_data
;
150 MALI_DEBUG_PRINT(2, ("No IRQ for core '%s' found during probe\n", description
));
157 /* Verify that the configured interrupt settings are working */
158 if (_MALI_OSK_ERR_OK
!= test_interrupt(irqnum
, trigger_func
, ack_func
, probe_data
, description
)) {
159 MALI_DEBUG_PRINT(2, ("Test of IRQ handler for core '%s' failed\n", description
));
166 if (0 != request_irq(irqnum
, irq_handler_upper_half
, IRQF_TRIGGER_LOW
, description
, irq_object
)) {
167 MALI_DEBUG_PRINT(2, ("Unable to install IRQ handler for core '%s'\n", description
));
175 void _mali_osk_irq_term( _mali_osk_irq_t
*irq
)
177 mali_osk_irq_object_t
*irq_object
= (mali_osk_irq_object_t
*)irq
;
178 free_irq(irq_object
->irqnum
, irq_object
);
183 /** This function is called directly in interrupt context from the OS just after
184 * the CPU get the hw-irq from mali, or other devices on the same IRQ-channel.
185 * It is registered one of these function for each mali core. When an interrupt
186 * arrives this function will be called equal times as registered mali cores.
187 * That means that we only check one mali core in one function call, and the
188 * core we check for each turn is given by the \a dev_id variable.
189 * If we detect an pending interrupt on the given core, we mask the interrupt
190 * out by settging the core's IRQ_MASK register to zero.
191 * Then we schedule the mali_core_irq_handler_bottom_half to run as high priority
194 static irqreturn_t
irq_handler_upper_half (int port_name
, void* dev_id
) /* , struct pt_regs *regs*/
196 irqreturn_t ret
= IRQ_NONE
;
197 mali_osk_irq_object_t
*irq_object
= (mali_osk_irq_object_t
*)dev_id
;
199 if (_MALI_OSK_ERR_OK
== irq_object
->uhandler(irq_object
->data
)) {