diff -r b7e488c49d0d -r 117faf51deac omap3530/beagle_drivers/wb/api/src/cyaslep2pep.c --- /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 +## +## /license/license.txt +## +## where 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 ; +}