omap3530/beagle_drivers/wb/api/src/cyaslep2pep.c
changeset 27 117faf51deac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omap3530/beagle_drivers/wb/api/src/cyaslep2pep.c	Wed Mar 03 13:10:32 2010 +0000
@@ -0,0 +1,337 @@
+/* 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 ;
+}