summaryrefslogtreecommitdiff
path: root/arch/arm/plat-mxc/sdma/iapi/src/iapiLow.c
blob: 47611fe5274339ea6b77ff8b8d968f8dde551a05 (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
/******************************************************************************
 *
 * Copyright 2007-2010 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: iapiLow.c
 *
 * $Id iapiLow.c $
 *
 * Description:
 *  This library is written in C to guarantee functionality and integrity in
 * the usage of SDMA virtual DMA channels. This API (Application Programming
 * Interface)  allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
 * fashion.
 *  These are the LOW level functions of the I.API.
 *
 *
 * /
 *
 * $Log iapiLow.c $
 *
 *****************************************************************************/

/* ****************************************************************************
 * Include File Section
 *****************************************************************************/
#include <linux/preempt.h>
#include <linux/hardirq.h>
#include "epm.h"
#include "iapiLow.h"

/**
 * Function Section
 */

/* ***************************************************************************/
/**Records an ISR callback function pointer into the ISR callback
 * function table
 *
 * @param cd_p channel descriptor to attach callback to
 * @param func_p pointer to the callback function to be registered
 *
 * @return none
 */
void
iapi_AttachCallbackISR(channelDescriptor *cd_p,
		       void (*func_p) (channelDescriptor *cd_p, void *arg))
{
	if (cd_p->callbackSynch == CALLBACK_ISR) {
		iapi_DisableInterrupts();
		callbackIsrTable[cd_p->channelNumber] = func_p;
		iapi_EnableInterrupts();
	} else if (cd_p->callbackSynch == DEFAULT_POLL) {
		callbackIsrTable[cd_p->channelNumber] = NULL;
	} else {
		iapi_errno =
		    IAPI_ERR_CALLBACKSYNCH_UNKNOWN | IAPI_ERR_CH_AVAILABLE |
		    cd_p->channelNumber;
	}
}

/* ***************************************************************************/
/**Detaches (removes) an ISR callback function pointer from the ISR callback
 * function table
 *
 * <b>Algorithm:</b>\n
 *    - Attach a null function to replace the original one.
 *
 * @param cd_p channel descriptor to detach callback from
 *
 * @return none
 */
void iapi_DetachCallbackISR(channelDescriptor *cd_p)
{
	iapi_AttachCallbackISR(cd_p, NULL);
}

/* ***************************************************************************/
/**Updates an ISR callback function pointer into the ISR callback function
 * table
 *
 * <b>Algorithm:</b>\n
 *    - Detach the old function pointer (if any) and attach the new one
 *
 * @param cd_p channel descriptor to attach callback to
 * @param func_p pointer to the callback function to be registered
 *
 * @return none
 */
void
iapi_ChangeCallbackISR(channelDescriptor *cd_p,
		       void (*func_p) (channelDescriptor *cd_p, void *arg))
{
	iapi_DetachCallbackISR(cd_p);
	iapi_AttachCallbackISR(cd_p, func_p);
}

/* ***************************************************************************/
/**Loop while the channel is not done on the SDMA
 *
 * <b>Algorithm:</b>\n
 *    - Loop doing nothing but checking the I.API global variable to indicate
 * that the channel has been completed (interrupt from SDMA)
 *
 * <b>Notes:</b>\n
 *    - The ISR must update the I.API global variable iapi_SDMAIntr.
 *
 * @param channel channel number to poll on
 *
 * @return none
 */
void iapi_lowSynchChannel(unsigned char channel)
{
	if (preempt_count() || in_interrupt()) {
		 while (!((1UL << channel) & iapi_SDMAIntr))
			 ;
	} else
		GOTO_SLEEP(channel);

	iapi_SDMAIntr &= ~(1UL << channel);
}

/* ***************************************************************************/
/**Fill the buffer descriptor with the values given in parameter.
 *
 * @return none
 */
void
iapi_SetBufferDescriptor(bufferDescriptor *bd_p, unsigned char command,
			 unsigned char status, unsigned short count,
			 void *buffAddr, void *extBufferAddr)
{
	bd_p->mode.command = command;
	bd_p->mode.status = status;
	bd_p->mode.count = count;
	if (buffAddr != NULL) {
		bd_p->bufferAddr = iapi_Virt2Phys(buffAddr);
	} else {
		bd_p->bufferAddr = buffAddr;
	}
	bd_p->extBufferAddr = extBufferAddr;
}