/*  ============================================================================
 *  Copyright (c) Texas Instruments Inc 2002, 2003, 2004, 2005
 *
 *  Use of this software is controlled by the terms and conditions found in the
 *  license agreement under which this software has been supplied.
 *  ===========================================================================
 */

/** @file csl_dmaxHwSetup.c
 *
 *  @brief File for functional layer of CSL API @a CSL_dmaxHwSetup()
 *
 *  Description
 *    - The @a CSL_dmaxHwSetup() function definition & it's associated
 *      functions
 *
 *  Modification 1
 *    - Modified on: 11/March/2005
 *    - Reason: created the sources
 * 
 *  @author asr.
 */

#include <csl_dmax.h>
/** =======================================================================
 *   @n@b CSL_dmaxHwSetup
 *
 *   @b Description
 *   @n This function initializes the device registers with the appropriate
 *      values provided through the HwSetup Data structure. After the 
 *      Setup is completed, the device is ready for  operation.      
 *      For information passed through the HwSetup Data structure refer
 *   @a CSL_dmaxHwSetup.
 *
 *   @b Arguments
 *   @verbatim
 *    
 *          hdmax   handle to the Dmax instance
 *          setup   Pointer to setup structure that programs DMAX
 *           
 *   @endverbatim
 *
 *   <b> Return Value </b>  CSL_Status
 *   @li                    CSL_SOK - Successful completion of hardware 
 *                                    setup
 *   @li                    CSL_ESYS_ INVPARAMS - Hardware structure is not
 *                                    properly initialized
 *   @li                    CSL_ESYS_ BADHANDLE - Invalid CSL handle
 *
 *
 *   <b> Pre Condition </b>
 *   @n  Both CSL_dmaxInit() and a CSL_dmaxOpen() must be called
 *
 *   <b> Post Condition </b>
 *   @n  DMAX registers are configured 
 *
 *   @b  Modifies
 *   @n  DMAX registers
 *
 *   @b Example
 *   @verbatim  
      CSL_dmaxHandle hDmax;
      CSL_dmaxHwSetup hwSetup;
      
    hwSetup.mode           = CSL_DMAX_MODE_MASTER;
    hwSetup.dir            = CSL_DMAX_DIR_TRANSMIT;
    hwSetup.addrMode       = CSL_DMAX_ADDRSZ_SEVEN;
    .
    .
    hwSetup.clksetup       = &clksetup;
    
      CSL_dmaxHwSetup(hDmax, &hwSetup);
     @endverbatim
 * 
 * ============================================================================
 */

#pragma CODE_SECTION (CSL_dmaxHwSetup, ".text:csl_section:dmax");

CSL_Status CSL_dmaxHwSetup (
    CSL_DmaxHandle 	hDmax,
    CSL_DmaxHwSetup *setup
)
{

    Uint8                   *tmpPtr;
    CSL_DmaxParameterEntry  *pEntry;
    CSL_DmaxGPTransferEventSetup *gpXfrEvent;
    CSL_DmaxFifoTransferEventSetup *fifoXfrEvent;
    CSL_DmaxCpuintEventSetup *cpuEvent;
    Uint16                   flag;
    Uint32                   tmpReg;
    Uint32                   ctrl;
    Uint32                   mask;
    Uint32                   val;
    Uint32                   locEtype;

    CSL_Status               status = CSL_SOK;

    if (hDmax == NULL)
        return CSL_ESYS_BADHANDLE;

    if (setup == NULL)
        return CSL_ESYS_INVPARAMS;

    /*  All the bits to be setup are initialiazed to zero
     *  before assigning the passed setup
     */

    if ((Int) hDmax != CSL_ESYS_BADHANDLE) {
        flag = hDmax->eventUid & 0xFFFF;
        mask = 1u << flag;
        tmpReg = hDmax->regs->DEPR;
        val = (setup->polarity == CSL_DMAX_POLARITY_RISING_EDGE) << flag;
        tmpReg |= val;
        hDmax->regs->DEPR = tmpReg;
        locEtype = ((CSL_DmaxEtype *) (setup->eventSetup))->etype;
        switch (locEtype) {
        case CSL_DMAX_EVENT0_ETYPE_GENERALXFR:
            {
                gpXfrEvent =
                    (CSL_DmaxGPTransferEventSetup *) (setup->eventSetup);
                ctrl =
                    CSL_FMK (DMAX_EVENT0_QTSL,
                    gpXfrEvent->qtsl) | CSL_FMK (DMAX_EVENT0_SYNC,
                    gpXfrEvent->sync) | CSL_FMK (DMAX_EVENT0_TCC,
                    gpXfrEvent->tcc) | CSL_FMK (DMAX_EVENT0_ATCINT,
                    gpXfrEvent->atcint) | CSL_FMK (DMAX_EVENT0_TCINT,
                    gpXfrEvent->tcint) | CSL_FMK (DMAX_EVENT0_RLOAD,
                    gpXfrEvent->rload) | CSL_FMK (DMAX_EVENT0_CC,
                    gpXfrEvent->cc) | CSL_FMK (DMAX_EVENT0_ESIZE,
                    gpXfrEvent->esize) | CSL_FMK (DMAX_EVENT0_PTE,
                    (gpXfrEvent->pte) +
                    CSL_DMAX_PTE_BASE_OFFSET) | CSL_FMK (DMAX_EVENT0_ETYPE,
                    gpXfrEvent->etype);
                break;
            }

        case CSL_DMAX_EVENT0_ETYPE_FIFOWRITE:
        case CSL_DMAX_EVENT0_ETYPE_FIFOREAD:
            {
                fifoXfrEvent =
                    (CSL_DmaxFifoTransferEventSetup *) (setup->eventSetup);
                ctrl =
                    CSL_FMK (DMAX_EVENT0_QTSL,
                    fifoXfrEvent->qtsl) | CSL_FMK (DMAX_EVENT0_SYNC,
                    fifoXfrEvent->sync) | CSL_FMK (DMAX_EVENT0_TCC,
                    fifoXfrEvent->tcc) | CSL_FMK (DMAX_EVENT0_ATCINT,
                    fifoXfrEvent->atcint) | CSL_FMK (DMAX_EVENT0_TCINT,
                    fifoXfrEvent->tcint) | CSL_FMK (DMAX_EVENT0_RLOAD,
                    fifoXfrEvent->rload) | CSL_FMK (DMAX_EVENT0_PTE,
                    ((fifoXfrEvent->pte) +
                        CSL_DMAX_PTE_BASE_OFFSET)) | CSL_FMK (DMAX_EVENT0_ETYPE,
                    fifoXfrEvent->etype);
                break;
            }

        case CSL_DMAX_EVENT30_ETYPE_CPUINT:
            {
                cpuEvent = (CSL_DmaxCpuintEventSetup *) (setup->eventSetup);
                ctrl = CSL_FMK (DMAX_EVENT0_INT, cpuEvent->cpuInt) |
                    CSL_FMK (DMAX_EVENT0_ETYPE, cpuEvent->etype);
//#define CSL_DMAX_EVENT0_INT_MASK        (0x00070000u)
//#define CSL_DMAX_EVENT0_INT_SHIFT       (0x00000010u)

                break;
            }

        default:
            {
                status = CSL_EDMAX_BAD_ETYPE;
            }
        }

        /* Init Parameter Table Entry */
        /* 
         *  The paramter table entry is actually 32 bits, but the paramPtr 
         *  offset is given in terms of byte offset from start of Parameter 
         *  Table. To get correct address, pEntry is defined as Uint8 *
         *  but data will be acessed as 32 bit.
         */
        if (status == CSL_SOK) {
            if (setup->priority == CSL_DMAX_HI_PRIORITY) {
                *(hDmax->hiTableEventEntryPtr) = ctrl;
                *(hDmax->loTableEventEntryPtr) = 0;

                hDmax->regs->DEHPR = mask;
                tmpPtr = (Uint8 *) (&(hDmax->regs->HiMaxParam));
            }
            else {
                *(hDmax->loTableEventEntryPtr) = ctrl;
                *(hDmax->hiTableEventEntryPtr) = 0;

                hDmax->regs->DELPR = mask;
                tmpPtr = (Uint8 *) (&(hDmax->regs->LoMaxParam));
            }

            tmpPtr += (hDmax->paramPtr) * CSL_DMAX_WORD_SIZE;
            pEntry = (CSL_DmaxParameterEntry *) tmpPtr;

            if (locEtype == CSL_DMAX_EVENT0_ETYPE_GENERALXFR) {
                CSL_dmaxSetupGeneralXFRParameterEntry (pEntry, gpXfrEvent->cc,
                    gpXfrEvent->paramSetup);
            }

            if ((locEtype == CSL_DMAX_EVENT0_ETYPE_FIFOREAD)
                || (locEtype == CSL_DMAX_EVENT0_ETYPE_FIFOWRITE)) {
                CSL_dmaxSetupFifoXFRParameterEntry (pEntry,
                    fifoXfrEvent->paramSetup);
            }
        }
    }
    else {
        status = CSL_ESYS_BADHANDLE;
    }
    return status;
}
