summaryrefslogtreecommitdiff
path: root/drivers/mxc/security/sahara2/sah_interrupt_handler.c
blob: 3d70fe8d2c64f329e1bd5ed3d39447b5465fafb1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/*
 * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved.
 */

/*
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

/*!
* @file sah_interrupt_handler.c
*
* @brief Provides a hardware interrupt handling mechanism for device driver.
*
* This file needs to be ported for a non-Linux OS.
*
* It gets a call at #sah_Intr_Init() during initialization.
*
* #sah_Intr_Top_Half() is intended to be the Interrupt Service Routine.  It
* calls a portable function in another file to process the Sahara status.
*
* #sah_Intr_Bottom_Half() is a 'background' task scheduled by the top half to
* take care of the expensive tasks of the interrupt processing.
*
* The driver shutdown code calls #sah_Intr_Release().
*
*/

#include <portable_os.h>

/* SAHARA Includes */
#include <sah_kernel.h>
#include <sah_interrupt_handler.h>
#include <sah_status_manager.h>
#include <sah_hardware_interface.h>
#include <sah_queue_manager.h>

/*Enable this flag for debugging*/
#if 0
#define DIAG_DRV_INTERRUPT
#endif

#ifdef DIAG_DRV_INTERRUPT
#include <diagnostic.h>
#endif

/*!
 * Number of interrupts received.  This value should only be updated during
 * interrupt processing.
 */
uint32_t interrupt_count;

#ifndef SAHARA_POLL_MODE

#if !defined(LINUX_VERSION_CODE) || LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#define irqreturn_t void
#define IRQ_HANDLED
#define IRQ_RETVAL(x)
#endif

/* Internal Prototypes */
static irqreturn_t sah_Intr_Top_Half(int irq, void *dev_id);

#ifdef KERNEL_TEST
extern void (*SAHARA_INT_PTR) (int, void *);
#endif

unsigned long reset_flag;
static void sah_Intr_Bottom_Half(unsigned long reset_flag);

/* This is the Bottom Half Task, (reset flag set to false) */
DECLARE_TASKLET(BH_task, sah_Intr_Bottom_Half, (unsigned long)&reset_flag);

/*! This is set by the Initialisation function */
wait_queue_head_t *int_queue = NULL;

/*!
*******************************************************************************
* This function registers the Top Half of the interrupt handler with the Kernel
* and the SAHARA IRQ number.
*
* @brief     SAHARA Interrupt Handler Initialisation
*
* @param    wait_queue Pointer to the wait queue used by driver interface
*
* @return   int A return of Zero indicates successful initialisation.
*/
/******************************************************************************
*
* CAUTION: NONE
*
* MODIFICATION HISTORY:
*
* Date         Person     Change
* 30/07/2003   MW         Initial Creation
******************************************************************************/
int sah_Intr_Init(wait_queue_head_t * wait_queue)
{

#ifdef DIAG_DRV_INTERRUPT
	char err_string[200];
#endif

	int result;

#ifdef KERNEL_TEST
	SAHARA_INT_PTR = sah_Intr_Top_Half;
#endif

	/* Set queue used by the interrupt handler to match the driver interface */
	int_queue = wait_queue;

	/* Request use of the Interrupt line. */
	result = request_irq(SAHARA_IRQ,
			     sah_Intr_Top_Half, 0, SAHARA_NAME, NULL);

#ifdef DIAG_DRV_INTERRUPT
	if (result != 0) {
		sprintf(err_string, "Cannot use SAHARA interrupt line %d. "
			"request_irq() return code is %i.", SAHARA_IRQ, result);
		LOG_KDIAG(err_string);
	} else {
		sprintf(err_string,
			"SAHARA driver registered for interrupt %d. ",
			SAHARA_IRQ);
		LOG_KDIAG(err_string);
	}
#endif

	return result;
}

/*!
*******************************************************************************
* This function releases the Top Half of the interrupt handler. The driver will
* not receive any more interrupts after calling this functions.
*
* @brief     SAHARA Interrupt Handler Release
*
* @return   void
*/
/******************************************************************************
*
* CAUTION: NONE
*
* MODIFICATION HISTORY:
*
* Date         Person     Change
* 30/07/2003   MW         Initial Creation
******************************************************************************/
void sah_Intr_Release(void)
{
	/* Release the Interrupt. */
	free_irq(SAHARA_IRQ, NULL);
}

/*!
*******************************************************************************
* This function is the Top Half of the interrupt handler.  It updates the
* status of any finished descriptor chains and then tries to add any pending
* requests into the hardware.  It then queues the bottom half to complete
* operations on the finished chains.
*
* @brief     SAHARA Interrupt Handler Top Half
*
* @param    irq     Part of the kernel prototype.
* @param    dev_id  Part of the kernel prototype.
*
* @return   An IRQ_RETVAL() -- non-zero to that function means 'handled'
*/
static irqreturn_t sah_Intr_Top_Half(int irq, void *dev_id)
{
#if defined(DIAG_DRV_INTERRUPT) && defined(DIAG_DURING_INTERRUPT)
	LOG_KDIAG("Top half of Sahara's interrupt handler called.");
#endif

	interrupt_count++;
	reset_flag = sah_Handle_Interrupt(sah_HW_Read_Status());

	/* Schedule the Bottom Half of the Interrupt. */
	tasklet_schedule(&BH_task);

	/* To get rid of the unused parameter warnings. */
	irq = 0;
	dev_id = NULL;
	return IRQ_RETVAL(1);
}

/*!
*******************************************************************************
* This function is the Bottom Half of the interrupt handler.  It calls
* #sah_postprocess_queue() to complete the processing of the Descriptor Chains
* which were finished by the hardware.
*
* @brief     SAHARA Interrupt Handler Bottom Half
*
* @param    data   Part of the kernel prototype.
*
* @return   void
*/
static void sah_Intr_Bottom_Half(unsigned long reset_flag)
{
#if defined(DIAG_DRV_INTERRUPT) && defined(DIAG_DURING_INTERRUPT)
	LOG_KDIAG("Bottom half of Sahara's interrupt handler called.");
#endif
	sah_postprocess_queue(*(unsigned long *)reset_flag);

	return;
}

/* end of sah_interrupt_handler.c */
#endif				/* ifndef SAHARA_POLL_MODE */