omap3530/beagle_drivers/wb/api/src/cyaslep2pep.c
author arunabha
Thu, 16 Sep 2010 14:35:26 +0100
changeset 70 ed23a53a5ee2
parent 23 117faf51deac
permissions -rw-r--r--
Fixing issues in base_beagle.iby which had references to DEBUG_DIR

/* Cypress West Bridge API source file (cyasusb.c)
## ===========================
##
##  Copyright Cypress Semiconductor Corporation, 2006-2009,
##  All Rights Reserved
##  UNPUBLISHED, LICENSED SOFTWARE.
##
##  CONFIDENTIAL AND PROPRIETARY INFORMATION
##  WHICH IS THE PROPERTY OF CYPRESS.
##
##  Use of this file is governed
##  by the license agreement included in the file
##
##     <install>/license/license.txt
##
##  where <install> is the Cypress software
##  installation root directory path.
##
## ===========================
*/

#include "cyashal.h"
#include "cyasusb.h"
#include "cyaserr.h"
#include "cyaslowlevel.h"
#include "cyasdma.h"

typedef enum CyAsPhysicalEndpointState
{
    CyAsEPFree,
    CyAsEPIn,
    CyAsEPOut,
    CyAsEPIsoIn,
    CyAsEPIsoOut
} CyAsPhysicalEndpointState;


/*
* This map is used to map an index between 1 and 10 to a logical endpoint number.  This
* is used to map LEP register indexes into actual EP numbers.
*/
static CyAsEndPointNumber_t EndPointMap[] = { 3, 5, 7, 9, 10, 11, 12, 13, 14, 15 } ;

#define CY_AS_EPCFG_1024            (1 << 3)
#define CY_AS_EPCFG_DBL             (0x02)
#define CY_AS_EPCFG_TRIPLE          (0x03)
#define CY_AS_EPCFG_QUAD            (0x00)

/*
 * NB: This table contains the register values for PEP1 and PEP3.  PEP2 and PEP4 only
 *     have a bit to change the direction of the PEP and therefre are not represented
 *     in this table.
 */
static uint8_t PepRegisterValues[12][4] =
{
    /* Bit 1:0 buffering, 0 = quad, 2 = double, 3 = triple */
    /* Bit 3 size, 0 = 512, 1 = 1024 */
    { 
        CY_AS_EPCFG_DBL, 
        CY_AS_EPCFG_DBL, 
    },      /* Config 1  - PEP1 (2 * 512), PEP2 (2 * 512), PEP3 (2 * 512), PEP4 (2 * 512) */
    { 
        CY_AS_EPCFG_DBL, 
        CY_AS_EPCFG_QUAD, 
    },      /* Config 2  - PEP1 (2 * 512), PEP2 (2 * 512), PEP3 (4 * 512), PEP4 (N/A) */
    { 
        CY_AS_EPCFG_DBL, 
        CY_AS_EPCFG_DBL | CY_AS_EPCFG_1024, 
    },      /* Config 3  - PEP1 (2 * 512), PEP2 (2 * 512), PEP3 (2 * 1024), PEP4(N/A) */
    { 
        CY_AS_EPCFG_QUAD, 
        CY_AS_EPCFG_DBL, 
    },      /* Config 4  - PEP1 (4 * 512), PEP2 (N/A), PEP3 (2 * 512), PEP4 (2 * 512) */
    { 
        CY_AS_EPCFG_QUAD, 
        CY_AS_EPCFG_QUAD, 
    },      /* Config 5  - PEP1 (4 * 512), PEP2 (N/A), PEP3 (4 * 512), PEP4 (N/A) */
    { 
        CY_AS_EPCFG_QUAD, 
        CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL, 
    },      /* Config 6  - PEP1 (4 * 512), PEP2 (N/A), PEP3 (2 * 1024), PEP4 (N/A) */
    { 
        CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL, 
        CY_AS_EPCFG_DBL, 
    },      /* Config 7  - PEP1 (2 * 1024), PEP2 (N/A), PEP3 (2 * 512), PEP4 (2 * 512) */
    { 
        CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL, 
        CY_AS_EPCFG_QUAD, 
    },      /* Config 8  - PEP1 (2 * 1024), PEP2 (N/A), PEP3 (4 * 512), PEP4 (N/A) */
    { 
        CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL, 
        CY_AS_EPCFG_1024 | CY_AS_EPCFG_DBL, 
    },      /* Config 9  - PEP1 (2 * 1024), PEP2 (N/A), PEP3 (2 * 1024), PEP4 (N/A)*/
    { 
        CY_AS_EPCFG_TRIPLE, 
        CY_AS_EPCFG_TRIPLE, 
    },      /* Config 10 - PEP1 (3 * 512), PEP2 (N/A), PEP3 (3 * 512), PEP4 (2 * 512)*/
    { 
        CY_AS_EPCFG_TRIPLE | CY_AS_EPCFG_1024, 
        CY_AS_EPCFG_DBL,
    },      /* Config 11 - PEP1 (3 * 1024), PEP2 (N/A), PEP3 (N/A), PEP4 (2 * 512) */
    { 
        CY_AS_EPCFG_QUAD | CY_AS_EPCFG_1024, 
        CY_AS_EPCFG_DBL,
    },      /* Config 12 - PEP1 (4 * 1024), PEP2 (N/A), PEP3 (N/A), PEP4 (N/A) */
} ;

static CyAsReturnStatus_t
FindEndpointDirections(CyAsDevice *dev_p, CyAsPhysicalEndpointState epstate[4])
{
    int i ;
    CyAsPhysicalEndpointState desired ;

    /*
     * Note, there is no error checking here becuase ISO error checking happens when
     * the API is called.
     */
    for(i = 0 ; i < 10 ; i++)
    {
        int epno = EndPointMap[i] ;
        if (dev_p->usb_config[epno].enabled)
        {
            int pep = dev_p->usb_config[epno].physical ;
            if (dev_p->usb_config[epno].type == CyAsUsbIso)
            {
                /*
                 * Marking this as an ISO endpoint, removes the physical EP from consideration when
                 * mapping the remaining EPs.
                 */
                if (dev_p->usb_config[epno].dir == CyAsUsbIn)
                    desired = CyAsEPIsoIn ;
                else
                    desired = CyAsEPIsoOut ;
            }
            else
            {
                if (dev_p->usb_config[epno].dir == CyAsUsbIn)
                    desired = CyAsEPIn ;
                else
                    desired = CyAsEPOut ;
            }

            /* NB: Note the API calls insure that an ISO endpoint has a physical and logical
             *     EP number that are the same, therefore this condition is not enforced here.
             */
            if (epstate[pep - 1] != CyAsEPFree && epstate[pep - 1] != desired)
                return CY_AS_ERROR_INVALID_CONFIGURATION ;

            epstate[pep - 1] = desired ;
        }
    }

    /*
     * Create the EP1 config values directly.
     * Both EP1OUT and EP1IN are invalid by default.
     */
    dev_p->usb_ep1cfg[0] = 0 ;
    dev_p->usb_ep1cfg[1] = 0 ;
    if (dev_p->usb_config[1].enabled)
    {
        if ((dev_p->usb_config[1].dir == CyAsUsbOut) || (dev_p->usb_config[1].dir == CyAsUsbInOut))
        {
            /* Set the valid bit and type field. */
            dev_p->usb_ep1cfg[0] = (1 << 7) ;
            if (dev_p->usb_config[1].type == CyAsUsbBulk)
                dev_p->usb_ep1cfg[0] |= (2 << 4) ;
            else
                dev_p->usb_ep1cfg[0] |= (3 << 4) ;
        }

        if ((dev_p->usb_config[1].dir == CyAsUsbIn) || (dev_p->usb_config[1].dir == CyAsUsbInOut))
        {
            /* Set the valid bit and type field. */
            dev_p->usb_ep1cfg[1] = (1 << 7) ;
            if (dev_p->usb_config[1].type == CyAsUsbBulk)
                dev_p->usb_ep1cfg[1] |= (2 << 4) ;
            else
                dev_p->usb_ep1cfg[1] |= (3 << 4) ;
        }
    }

    return CY_AS_ERROR_SUCCESS ;
}

static void
CreateRegisterSettings(CyAsDevice *dev_p, CyAsPhysicalEndpointState epstate[4])
{
    int i ;
    uint8_t v ;

    for(i = 0 ; i < 4 ; i++)
    {
        if (i == 0)
            dev_p->usb_pepcfg[i] = PepRegisterValues[dev_p->usb_phy_config - 1][0] ;    /* Start with the values that specify size */
        else if (i == 2)
            dev_p->usb_pepcfg[i] = PepRegisterValues[dev_p->usb_phy_config - 1][1] ;    /* Start with the values that specify size */
        else
            dev_p->usb_pepcfg[i] = 0 ;

        if (epstate[i] == CyAsEPIsoIn || epstate[i] == CyAsEPIn)
            dev_p->usb_pepcfg[i] |= (1 << 6) ;                                          /* Adjust direction if it is in */
    }

    /* Configure the logical EP registers */
    for(i = 0 ; i < 10 ; i++)
    {
        int val ;
        int epnum = EndPointMap[i] ;

        v = 0x10 ;      /* PEP 1, Bulk Endpoint, EP not valid */
        if (dev_p->usb_config[epnum].enabled)
        {
            v |= (1 << 7) ;                                             /* Enabled */

            val = dev_p->usb_config[epnum].physical - 1 ;
            CyAsHalAssert(val >= 0 && val <= 3) ;
            v |= (val << 5) ;

            switch(dev_p->usb_config[epnum].type)
            {
            case CyAsUsbBulk:
                val = 2 ;
                break ;
            case CyAsUsbInt:
                val = 3 ;
                break ;
            case CyAsUsbIso:
                val = 1 ;
                break ;
            default:
                CyAsHalAssert(CyFalse) ;
                break ;
            }
            v |= (val << 3) ;
        }

        dev_p->usb_lepcfg[i] = v ;
    }
}


CyAsReturnStatus_t
CyAsUsbMapLogical2Physical(CyAsDevice *dev_p)
{
    CyAsReturnStatus_t ret ;

    /* Physical EPs 3 5 7 9 respectively in the array */
    CyAsPhysicalEndpointState epstate[4] = { CyAsEPFree, CyAsEPFree, CyAsEPFree, CyAsEPFree } ;

    /* Find the direction for the endpoints */
    ret = FindEndpointDirections(dev_p, epstate) ;
    if (ret != CY_AS_ERROR_SUCCESS)
        return ret ;

    /*
     * Now create the register settings based on the given assigned of logical EPs to
     * physical endpoints.
     */
    CreateRegisterSettings(dev_p, epstate) ;

    return ret ;
}

static uint16_t
GetMaxDmaSize(CyAsDevice *dev_p, CyAsEndPointNumber_t ep)
{
    uint16_t size = dev_p->usb_config[ep].size ;

    if (size == 0)
    {
        switch(dev_p->usb_config[ep].type)
        {
        case CyAsUsbControl:
            size = 64 ;
            break ;

        case CyAsUsbBulk:
            size = CyAsDeviceIsUsbHighSpeed(dev_p) ? 512 : 64 ;
            break ;

        case CyAsUsbInt:
            size = CyAsDeviceIsUsbHighSpeed(dev_p) ? 1024 : 64 ;
            break ;

        case CyAsUsbIso:
            size = CyAsDeviceIsUsbHighSpeed(dev_p) ? 1024 : 1023 ;
            break ;
        }
    }

    return size ;
}

CyAsReturnStatus_t
CyAsUsbSetDmaSizes(CyAsDevice *dev_p)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    uint32_t i ;

    for(i = 0 ; i < 10 ; i++)
    {
        CyAsUsbEndPointConfig *config_p = &dev_p->usb_config[EndPointMap[i]] ;
        if (config_p->enabled)
        {
            ret = CyAsDmaSetMaxDmaSize(dev_p, EndPointMap[i], GetMaxDmaSize(dev_p, EndPointMap[i])) ;
            if (ret != CY_AS_ERROR_SUCCESS)
                break ;
        }
    }

    return ret ;
}

CyAsReturnStatus_t
CyAsUsbSetupDma(CyAsDevice *dev_p)
{
    CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
    uint32_t i ;

    for(i = 0 ; i < 10 ; i++)
    {
        CyAsUsbEndPointConfig *config_p = &dev_p->usb_config[EndPointMap[i]] ;
        if (config_p->enabled)
        {
            /* Map the endpoint direction to the DMA direction */
            CyAsDmaDirection dir = CyAsDirectionOut ;
            if (config_p->dir == CyAsUsbIn)
                dir = CyAsDirectionIn ;

            ret = CyAsDmaEnableEndPoint(dev_p, EndPointMap[i], CyTrue, dir) ;
            if (ret != CY_AS_ERROR_SUCCESS)
                break ;
        }
    }

    return ret ;
}