summaryrefslogtreecommitdiff
path: root/arch/arm/plat-mxc/sdma/iapi/src/iapiLowMcu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-mxc/sdma/iapi/src/iapiLowMcu.c')
-rw-r--r--arch/arm/plat-mxc/sdma/iapi/src/iapiLowMcu.c503
1 files changed, 503 insertions, 0 deletions
diff --git a/arch/arm/plat-mxc/sdma/iapi/src/iapiLowMcu.c b/arch/arm/plat-mxc/sdma/iapi/src/iapiLowMcu.c
new file mode 100644
index 000000000000..345d36433cf3
--- /dev/null
+++ b/arch/arm/plat-mxc/sdma/iapi/src/iapiLowMcu.c
@@ -0,0 +1,503 @@
+/******************************************************************************
+ *
+ * Copyright 2007-2011 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: iapiLowMcu.c
+ *
+ * $Id iapiLowMcu.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 specific to MCU.
+ *
+ *
+ * http://compass/mot.com/go/115342679
+ *
+ * $Log iapiLowMcu.c $
+ *
+ *****************************************************************************/
+
+/* ****************************************************************************
+ * Include File Section
+ *****************************************************************************/
+#include <string.h>
+#include <io.h>
+
+#include "epm.h"
+#include "iapiLow.h"
+
+/* ****************************************************************************
+ * Function Section
+ *****************************************************************************/
+#ifdef MCU
+
+/* ***************************************************************************/
+/**Send a command on SDMA's channel zero.
+ * Check if buffer descriptor is already used by the sdma, if yes return
+ * an error as c0BDNum is wrong.
+ *
+ * <b>Notes</b>\n
+ * There is an upgrade in the script on the Context load command and
+ * the fact that the context structure has a fixed length of 20 or 24
+ * depending on SDMA versions.
+ *
+ * @return
+ * - IAPI_SUCCESS
+ * - -iapi_errno if failure
+ */
+int
+iapi_Channel0Command(channelDescriptor *cd_p, void *buf,
+ unsigned short nbyte, unsigned char command)
+{
+ channelControlBlock *ccb_p;
+ bufferDescriptor *bd_p;
+ int result = IAPI_SUCCESS;
+ unsigned char chNum;
+
+ /*
+ * Check data structures are properly initialized
+ */
+ /* Channel descriptor validity */
+ if (cd_p == NULL) {
+ result = IAPI_ERR_CD_UNINITIALIZED;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Channel control block validity */
+ if (cd_p->ccb_ptr == NULL) {
+ result = IAPI_ERR_CCB_UNINITIALIZED;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Control block & Descriptpor associated with the channel being worked on */
+ chNum = cd_p->channelNumber;
+ ccb_p = cd_p->ccb_ptr;
+
+ /* Is channel already in use ? */
+ if (ccb_p->baseBDptr != NULL) {
+ result = IAPI_ERR_BD_ALLOCATED | IAPI_ERR_CH_AVAILABLE | chNum;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Allocation of buffer descriptors */
+ bd_p = (bufferDescriptor *) MALLOC(sizeof(bufferDescriptor), SDMA_ERAM);
+ if (bd_p != NULL) {
+ ccb_p->baseBDptr = (bufferDescriptor *) iapi_Virt2Phys(bd_p);
+ } else {
+ result = IAPI_ERR_BD_ALLOCATION | IAPI_ERR_CH_AVAILABLE | chNum;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Buffer descriptor setting */
+ iapi_SetBufferDescriptor(bd_p, command, BD_WRAP | BD_DONE | BD_INTR,
+ nbyte, buf, NULL);
+
+ /* Actually the transfer */
+ iapi_lowStartChannel(cd_p->channelNumber);
+ iapi_lowSynchChannel(cd_p->channelNumber);
+
+ /* Cleaning of allocation */
+ FREE(bd_p);
+ ccb_p->baseBDptr = NULL;
+
+ return IAPI_SUCCESS;
+
+}
+
+/* ***************************************************************************/
+/**Starts the channel (core specific register)
+ *
+ * <b>Algorithm:</b>\n
+ * - Bit numbered "channel" of HostEnStartReg register is set
+ *
+ * @param channel channel to start
+ *
+ * @return none
+ */
+void iapi_lowStartChannel(unsigned char channel)
+{
+ /* HSTART is a 'write-ones' register */
+ writel(1UL << channel, SDMA_H_START_ADDR);
+}
+
+/* ***************************************************************************/
+/**Stops the channel (core specific register)
+ *
+ * <b>Algorithm:</b>
+ * - Bit numbered "channel" of HostEnStopReg register is cleared
+ *
+ * <b>Notes:</b>\n
+ * - This is a write one to clear register
+ *
+ * @param channel channel to stop
+ *
+ * @return none
+ */
+void iapi_lowStopChannel(unsigned char channel)
+{
+ /* Another 'write-ones' register */
+ writel(1UL << channel, SDMA_H_STATSTOP_ADDR);
+}
+
+/* ***************************************************************************/
+/**Initialize the initial priority of registers and channel enable
+ * RAM from the MCU side. No channels are enabled, all priorities are set to 0.
+ *
+ * @return none
+ */
+void iapi_InitChannelTables(void)
+{
+
+ /* No channel is enabled */
+ iapi_memset((void *)&SDMA_CHNENBL_0, 0x00,
+ sizeof(unsigned long) * EVENTS_NUM);
+ /* All channels have priority 0 */
+ iapi_memset((void *)&SDMA_CHNPRI_0, 0x00,
+ sizeof(unsigned long) * CH_NUM);
+}
+
+/* ***************************************************************************/
+/** The host enable (HE), hosts override (HO), dsp enable (DE), dsp override
+ * (DO) registers are involved here.
+ * Host and Dsp enable registers are here to signify that the MCU or DSP side
+ * have prepared the appropriate buffers and are now ready. If the channel is
+ * owned by the MCU the override bit for that channel needs to be cleared :
+ * the host allows the channel to be used.\n
+ *
+ * Then the override bits can define (mcuOverride dspOverride):\n
+ * - 0 0 channel is public: transfer to/from MCU to DSP
+ * - 0 1 channel if owned by DSP
+ * - 1 0 channel if owned by MCU
+ * - 1 1 channel zero config
+ *
+ * See also :\n
+ * IAPI Table 1.1 "Channel configuration properties"
+ *
+ * @param channel channel to configure
+ * @param eventOverride event ownership
+ * @param mcuOverride ARM ownership
+ * @param dspOverride DSP ownership
+ *
+ * @return
+ * - -iapi_errno if the 3 override parameters are all set
+ * - IAPI_SUCCESS in other cases (valid cases)
+ */
+int
+iapi_ChannelConfig(unsigned char channel, unsigned eventOverride,
+ unsigned mcuOverride, unsigned dspOverride)
+{
+ int result = IAPI_SUCCESS;
+
+ if ((eventOverride == 1) && (mcuOverride == 1) && (dspOverride == 1)) {
+ result = IAPI_ERR_CONFIG_OVERRIDE;
+ iapi_errno = result;
+ return -result;
+ } else {
+ /*
+ * DSP side
+ */
+ if (dspOverride) {
+ SDMA_H_DSPOVR &= ~(1 << channel);
+ } else {
+ SDMA_H_DSPOVR |= (1 << channel);
+ }
+ /*
+ * Event
+ */
+ if (eventOverride) {
+ SDMA_H_EVTOVR &= ~(1 << channel);
+ } else {
+ SDMA_H_EVTOVR |= (1 << channel);
+ }
+ /*
+ * MCU side
+ */
+ if (mcuOverride) {
+ SDMA_H_HOSTOVR &= ~(1 << channel);
+ } else {
+ SDMA_H_HOSTOVR |= (1 << channel);
+ }
+ }
+ return IAPI_SUCCESS;
+}
+
+/* ***************************************************************************/
+/**Load the context data of a channel from SDMA
+ *
+ * <b>Algorithm:</b>\n
+ * - Setup BD with appropiate parameters
+ * - Start channel
+ * - Poll for answer
+ *
+ * @param *cd_p channel descriptor for channel 0
+ * @param *buf pointer to receive context data
+ * @param channel channel for which the context data is requested
+ *
+ * @return none
+ */
+void
+iapi_lowGetContext(channelDescriptor *cd_p, void *buf, unsigned char channel)
+{
+ bufferDescriptor *bd_p;
+
+ bd_p = (bufferDescriptor *) iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+
+ /*Setup buffer descriptor with channel 0 command */
+ iapi_SetBufferDescriptor(&bd_p[0],
+ C0_GETDM,
+ (unsigned char)(BD_DONE | BD_INTR | BD_WRAP |
+ BD_EXTD),
+ (unsigned short)sizeof(contextData) / 4, buf,
+ (void *)(CHANNEL_CONTEXT_BASE_ADDRESS +
+ (sizeof(contextData) * channel / 4)));
+ /* Receive, polling method */
+ iapi_lowStartChannel(cd_p->channelNumber);
+ iapi_lowSynchChannel(cd_p->channelNumber);
+}
+
+/* ***************************************************************************/
+/**Read "size" byte /2 at SDMA address (address) and write them in buf
+ *
+ * <b>Algorithm:</b>\n
+ * - Setup BD with appropiate parameters (C0_GETPM)
+ * - Start channel
+ * - Poll for answer
+ *
+ * <b>Notes</b>\n
+ * - Parameter "size" is in bytes, it represents the size of "buf", e.g.
+ * the size in bytes of the script to be loaded.
+ * - Parameter "address" denotes the RAM address for the script in SDMA
+ *
+ * @param *cd_p channel descriptor for channel 0
+ * @param *buf pointer to receive the data
+ * @param size number of bytes to read
+ * @param address address in SDMA RAM to start reading from
+ *
+ * @return none
+ */
+void
+iapi_lowGetScript(channelDescriptor *cd_p, void *buf, unsigned short size,
+ unsigned long address)
+{
+ bufferDescriptor *bd_p;
+
+ bd_p = (bufferDescriptor *) iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+
+ /*Setup buffer descriptor with channel 0 command */
+ iapi_SetBufferDescriptor(&bd_p[0], C0_GETPM, (unsigned char)(BD_DONE | BD_INTR | BD_WRAP | BD_EXTD), (unsigned short)size / 2, /*count in shorts */
+ buf, (void *)address);
+ /* Receive, polling method */
+ iapi_lowStartChannel(cd_p->channelNumber);
+ iapi_lowSynchChannel(cd_p->channelNumber);
+}
+
+/* ***************************************************************************/
+/**Load a SDMA script to SDMA
+ *
+ * <b>Algorithm:</b>\n
+ * - Setup BD with appropiate parameters (C0_SETPM)
+ * - Start channel
+ * - Poll for answer
+ *
+ * <b>Notes</b>\b
+ * - Parameter "size" is in bytes, it represents the size of "buf", e.g.
+ * the size in bytes of the script to be uploaded.
+ * - Parameter "address" denotes the RAM address for the script in SDMA
+ *
+ * @param *cd_p channel descriptor for channel 0
+ * @param *buf pointer to the script
+ * @param size size of the script, in bytes
+ * @param address address in SDMA RAM to place the script
+ *
+ * @return none
+ */
+void
+iapi_lowSetScript(channelDescriptor *cd_p, void *buf, unsigned short size,
+ unsigned long address)
+{
+ bufferDescriptor *bd_p;
+
+ bd_p = (bufferDescriptor *) iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+
+ /*Setup buffer descriptor with channel 0 command */
+ iapi_SetBufferDescriptor(&bd_p[0], C0_SETPM, (unsigned char)(BD_DONE | BD_INTR | BD_WRAP | BD_EXTD), (unsigned short)size / 2, /*count in shorts */
+ buf, (void *)(address));
+ /* Receive, polling method */
+ iapi_lowStartChannel(cd_p->channelNumber);
+ iapi_lowSynchChannel(cd_p->channelNumber);
+}
+
+/* ***************************************************************************/
+/**Load the context for a channel to SDMA
+ *
+ * <b>Algorithm:</b>\n
+ * - Send context and poll for answer.
+ *
+ * @param *cd_p channel descriptor for channel 0
+ * @param *buf pointer to context data
+ * @param channel channel to place the context for
+ *
+ * @return none
+ */
+void
+iapi_lowSetContext(channelDescriptor *cd_p, void *buf, unsigned char channel)
+{
+
+ bufferDescriptor *local_bd_p;
+#ifdef SDMA_SKYE
+
+ unsigned char command = 0;
+
+ local_bd_p =
+ (bufferDescriptor *) iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+
+ command = channel << 3;
+ command = command | C0_SETCTX;
+ iapi_SetBufferDescriptor(&local_bd_p[0],
+ command,
+ (unsigned char)(BD_DONE | BD_INTR | BD_WRAP),
+ (unsigned short)(sizeof(contextData) / 4),
+ buf, NULL);
+#else
+
+ local_bd_p =
+ (bufferDescriptor *) iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
+
+ iapi_SetBufferDescriptor(&local_bd_p[0],
+ C0_SETDM,
+ (unsigned char)(BD_DONE | BD_INTR | BD_WRAP |
+ BD_EXTD),
+ (unsigned short)(sizeof(contextData) / 4), buf,
+ (void *)(2048 +
+ (sizeof(contextData) / 4) * channel));
+#endif
+ /* Send */
+ iapi_lowStartChannel(cd_p->channelNumber);
+ iapi_lowSynchChannel(cd_p->channelNumber);
+
+}
+
+/* ***************************************************************************/
+/**Associate specified channel with the script starting at the
+ * specified address. Channel 0 command is used to load the set-up context
+ * for the channel. The address used must be generated by the GUI tool
+ * used to create RAM images for SDMA.
+ *
+ * <b>Algorithm:</b>\n
+ * - Set-up and load the context.
+ *
+ * @param *cd_p pointer to the channel descriptor of the channel
+ * @param *data_p: pointer to the data identifying the script to be associated
+ * with the channel
+ *
+ * @return
+ * - IAPI_SUCCESS : OK
+ * - -iapi_errno : operation failed, return negated value of iapi_errno
+ */
+
+int iapi_lowAssignScript(channelDescriptor *cd_p, script_data * data_p)
+{
+ contextData *chContext; /* context to be loaded for the channel */
+ channelDescriptor *cd0_p; /* pointer to channel descriptor of channel 0 */
+ int result = IAPI_SUCCESS;
+
+ /*Verify passed data */
+ if (cd_p == NULL || data_p == NULL) {
+ result = IAPI_ERR_INVALID_PARAMETER;
+ iapi_errno = result;
+ return -result;
+ }
+
+ /* Allocate context and initialize PC to required script start adress */
+ chContext = (contextData *) MALLOC(sizeof(contextData), SDMA_ERAM);
+ if (chContext == NULL) {
+ result = IAPI_ERR_B_ALLOC_FAILED | cd_p->channelNumber;
+ iapi_errno = result;
+ return -result;
+ }
+
+ iapi_memset(chContext, 0x00, sizeof(contextData));
+ chContext->channelState.pc = data_p->load_address;
+
+ /* Send by context the event mask,base address for peripheral
+ * and watermark level
+ */
+ chContext->gReg[0] = data_p->event_mask2;
+ chContext->gReg[1] = data_p->event_mask1;
+ chContext->gReg[6] = data_p->shp_addr;
+ chContext->gReg[7] = data_p->wml;
+ if (data_p->per_addr)
+ chContext->gReg[2] = data_p->per_addr;
+
+ /* Set transmited data to the CD */
+ cd_p->watermarkLevel = data_p->wml;
+ cd_p->eventMask1 = data_p->event_mask1;
+ cd_p->eventMask2 = data_p->event_mask2;
+
+ /* Get the cd0_p */
+ cd0_p = (cd_p->ccb_ptr - cd_p->channelNumber)->channelDescriptor;
+
+ /*load the context */
+ iapi_lowSetContext(cd0_p, chContext, cd_p->channelNumber);
+
+ /* release allocated memory */
+ FREE(chContext);
+
+ return IAPI_SUCCESS;
+}
+
+/* ***************************************************************************/
+/** Set the channels to be triggered by an event. The for every channel that
+ *must be triggered by the event, the corresponding bit from channel_map
+ *parameter must be set to 1. (e.g. for the event to trigger channels 31 and
+ *0 one must pass 0x80000001)
+ *
+ *
+ * <b>Algorithm:</b>\n
+ * - Update the register from Channel Enable RAM with the channel_map
+ *
+ * @param event event for which to set the channel association
+ * @param channel_map channels to be triggered by event. Put the corresponding
+ * bit from this 32-bit value to 1 for every channel that should be
+ * triggered by the event.
+ *
+ * @return
+ * - IAPI_SUCCESS : OK
+ * - -iapi_errno : operation failed, return negated value of iapi_errno
+ */
+int
+iapi_lowSetChannelEventMapping(unsigned char event, unsigned long channel_map)
+{
+ volatile unsigned long *channelEnableMatx;
+ int result = IAPI_SUCCESS;
+
+ /* Check validity of event */
+ if (event < EVENTS_NUM) {
+ channelEnableMatx = &SDMA_CHNENBL_0;
+ channelEnableMatx[event] |= channel_map;
+ return result;
+ } else {
+ result = IAPI_ERR_INVALID_PARAMETER | event;
+ iapi_errno = result;
+ return -result;
+ }
+}
+
+#endif /* MCU */