⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcmciapower.cpp

📁 EP9315开发板的Wince6.0的BSP包文件
💻 CPP
字号:
//**********************************************************************
//                                                                      
// Filename: pcmciapower.cpp
//                                                                      
// Description: Routine to set the voltage on the PCMCIA card.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Use of this source code is subject to the terms of the Cirrus end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to 
// use this source code. For a copy of the EULA, please see the 
// EULA.RTF on your install media.
//
// Copyright(c) Cirrus Logic Corporation 2005, All Rights Reserved
//                                                                      
//**********************************************************************
#include <windows.h>
#include <hwdefs.h>
#include <clocks.h>
#include "pdsocket.h"


static unsigned char Vcc  = 0;
static unsigned char Vpp1 = 0;
static unsigned char Vpp2 = 0;

#define ERROR_POWERPCCARD_INVALID_PARMS 1
#define ERROR_POWERPCCARD_TIMEOUT       2

//
// Definitions to program the TPS2202A PCMCIA controller.
//
#define     AVPP_0V         0x000
#define     AVPP_VCC        0x002
#define     AVPP_12V        0x001
#define     BVPP_0V         0x000
#define     BVPP_VCC        0x020
#define     BVPP_12V        0x010
#define     AVCC_0V         0x000
#define     AVCC_33V        0x004
#define     AVCC_5V         0x008
#define     BVCC_0V         0x000
#define     BVCC_33V        0x080
#define     BVCC_5V         0x040
#define     ENABLE          0x100
#define     EE_ADDRESS      (0x55<<9)

//
// The propagation delay of the EP931x board.  
// Don't know what this number is.  This number is probably high right now.
//
#define PCMCIA_BOARD_DELAY          40

//****************************************************************************
// DelayuS
//****************************************************************************
//
void DelayInuSec(DWORD uS)
{
    DWORD passed, startTime;

    startTime= *TIM_DEBUGVALUELOW;
    passed=0;
    
    //
    // Get stuck in this loop until 
    //
    while ( passed < uS ) 
    {
       passed = (*TIM_DEBUGVALUELOW - startTime);

	   if( passed > (UINT16)-1 ) //timer wrap.
	   {
		   passed= *TIM_DEBUGVALUELOW + ( (DWORD)-1 - startTime );
	   }
    }
}



//****************************************************************************
// PowerPCCardWrite
//****************************************************************************
// Sets the voltage levels to the PCMCIA cards.
// 
//
BOOL CPcmciaBusBridge::PowerPCCardWrite(  unsigned char vccOut,  unsigned char vpp1Out )
{    
    BOOL   retVal = 0;    // 0 = G_SUCCESS
    ULONG           ulSwitchSettings;
    int             i;
    
    ulSwitchSettings = EE_ADDRESS |ENABLE | BVPP_0V | BVCC_0V ;
    
	RETAILMSG(TRUE, (TEXT("PowerPCCardWrite %d \r\n"), vccOut));
    //
    // Set up VCC A and B.  This way we can set 
    // the battery volatage to anything.
    //
    switch( vccOut)
    {
        case 0:
            ulSwitchSettings |= AVCC_0V;
            break;

        case 33:
            ulSwitchSettings |= AVCC_33V;
            break;

        case 50:
            ulSwitchSettings |= AVCC_5V;
            break;

        default:
            return (ERROR_POWERPCCARD_INVALID_PARMS);
    }

    //
    // Set up the battery voltage vpp1.
    //
    if(vpp1Out == 0)
    {
        ulSwitchSettings |= AVPP_0V;
    }
    else if(vpp1Out == 120)
    {
        ulSwitchSettings |= AVPP_12V;
    }
    else if(vpp1Out == vccOut)
    {
        ulSwitchSettings |= AVPP_VCC;
    }
    else
    {
        return (ERROR_POWERPCCARD_INVALID_PARMS);
    }
    

    //
    // Update these variables while processing
    //
    Vcc = vccOut;      
    Vpp1 = vpp1Out;
    Vpp2 = 0;             


    //
    // TODO - Put I2C mutex here.
    //

    //
    // Turn on the power to the socket !!!
    //
    //  EECLK  -> Clock
    //  EEDATA -> Data
    //  SLA0   -> Latch
    //*EEPROM_CONFIG   =  CONFIG_S0DIR;
    //Sleep(20);
    //*EEPROM_CONFIG   =  CONFIG_S0DIR | CONFIG_DDIR | CONFIG_CDIR ;
    *GPIO_PGDDR         =  GPIOG_EECLK | GPIOG_EEDAT | GPIOG_SLA0;
 
    
    //
    // Clear all except EECLK
    // 
    //*EEPROM_DATA     = DATA_EECLK;
    *GPIO_PGDR          = GPIOG_EECLK;

    //
    // Raise the clock.
    //    
    DelayInuSec(50);
    //*EEPROM_DATA     = 0;
    *GPIO_PGDR          = 0;
    DelayInuSec(50);

    for (i=18; i>=0; --i)
    //for (i=9; i>=0; --i)
    {
        if((ulSwitchSettings >> i) & 1)
        {
            //
            // Put the data on the bus and lower the clock.
            //
            *GPIO_PGDR = GPIOG_EEDAT ;
            DelayInuSec(50);
        
            //
            // Raise the clock to latch the data in.
            //
            //*EEPROM_DATA    = DATA_EECLK | DATA_EEDAT;
            *GPIO_PGDR       = GPIOG_EECLK | GPIOG_EEDAT;
            DelayInuSec(50);

            //
            // Lower the clock again.
            //        
            //*EEPROM_DATA     = DATA_EEDAT;
            *GPIO_PGDR        = GPIOG_EEDAT;
            DelayInuSec(50);
        }
        else            
        {
            //
            // Put the data on the bus and lower the clock.
            //
            //*EEPROM_DATA    = 0 ;
            *GPIO_PGDR       = 0;
            DelayInuSec(50);
        
            //
            // Raise the clock to latch the data in.
            //
            //*EEPROM_DATA     = DATA_EECLK ;
            *GPIO_PGDR       = GPIOG_EECLK ;
            DelayInuSec(50);

            //
            // Lower the clock again.
            //        
            //*EEPROM_DATA     = 0;
            *GPIO_PGDR       = 0 ;
            DelayInuSec(50);
        }                    
    }
        
    //
    // Raise and lower the Latch.
    //
    *GPIO_PGDR       = GPIOG_SLA0;
    DelayInuSec(50);

    *GPIO_PGDR       = 0;
    *GPIO_PGDR       = GPIOG_EECLK;
    DelayInuSec(50);
    *GPIO_PGDR       = GPIOG_EECLK| GPIOG_EEDAT;
    DelayInuSec(50);
    
    //
    // Change the configuration back to zero.
    // This will cause the PCMCIA interface to reset.
    //
    //*EEPROM_CONFIG  = CONFIG_S0DIR;

	RETAILMSG(TRUE, (TEXT("PowerPCCardWrite %d  success\r\n"), vccOut));

    return(retVal);
}

UINT32 CalculatePcmciaTimings
(
    UINT32 NsSpeed
)
{
    ULONG   ulAddressTime;
    ULONG   ulHoldTime;
    ULONG   ulAccessTime;
    ULONG   ulSMC;
    ULONG   ulHCLK = REAL_HCLOCK;
    ULONG   ulHPeriod;
    ULONG   ulHAccessTime;
    ULONG   ulHAddressTime;
    ULONG   ulHHoldTime;
    
	DEBUGMSG(1,(TEXT("CalculatePcmciaTimings %d \r\n"), NsSpeed));

    switch(NsSpeed)
    {
        case 600:
        case 0:
        default:
            ulAccessTime    = 600;
            ulAddressTime   = 100;
            ulHoldTime      = 35;
            break;
            
        case 300:
            ulAccessTime    = 300;
            ulAccessTime    = 300;
            ulAddressTime   = 30;
            ulHoldTime      = 20;
            break;
            
        case 250:
            ulAccessTime    = 250 - 30 - 20;
            ulAddressTime   = 30;
            ulHoldTime      = 20;
            break;
            
        case 200:
            ulAccessTime    = 200 - 20 - 20;
            ulAddressTime   = 20;
            ulHoldTime      = 20;
            break;
            
        case 150:
            ulAccessTime    = 150 - 20 - 20;
            ulAddressTime   = 20;
            ulHoldTime      = 20;
            break;
            
        case 100:
            ulAccessTime    = 100 - 10 - 15;  
            ulAddressTime   = 10;
            ulHoldTime      = 15;
            break;
            
        //
        // Special case for I/O all access.
        //            
        //case 0:
        //    ulAccessTime    = 165 - 70 - 20;
        //    ulAccessTime    = 200;
        //    ulAddressTime   = 70;
        //    ulHoldTime      = 20;
        //     break;
    }

    //
    // Add in a board delay.
    //
    ulAccessTime    += PCMCIA_BOARD_DELAY;
    ulAddressTime   += PCMCIA_BOARD_DELAY;
    ulHoldTime      += PCMCIA_BOARD_DELAY;
    
    //
    // This gives us the period in nanosecods.
    //
    // = 1000000000 (ns/s) / HCLK (cycle/s)
    //
    // = (ns/cycle)
    //
    ulHPeriod       = (1000000000/ ulHCLK);
    
    //
    // Find the number of hclk cycles for cycle time, address time and
    // hold time.
    //
    // = ulAccessTime   (ns) / ulHPeriod (ns/Cycles)
    // = ulAddressTime (ns) / ulHPeriod (ns/Cycles)
    // = ulHoldTime    (ns) / ulHPeriod (ns/Cycles)
    //
    ulHAccessTime    = (ulAccessTime + ulHPeriod - 1) / ulHPeriod;
    if(ulHAccessTime > 0xFF)
    {
        ulHAccessTime  = 0xFF;
    }
    
    ulHAddressTime  = (ulAddressTime + ulHPeriod - 1) / ulHPeriod;
    if(ulHAddressTime > 0xFF)
    {
        ulHAddressTime = 0xFF;
    }
            
    ulHHoldTime     = ((ulHoldTime + ulHPeriod - 1) / ulHPeriod) + 1;
    if(ulHHoldTime >0xF)
    {
        ulHHoldTime     = 0xF;
    }

    ulSMC = (PCCONFIG_ADDRESSTIME_MASK & (ulHAddressTime << PCCONFIG_ADDRESSTIME_SHIFT)) |
            (PCCONFIG_HOLDTIME_MASK & (ulHHoldTime << PCCONFIG_HOLDTIME_SHIFT)) |
            (PCCONFIG_ACCESSTIME_MASK & (ulHAccessTime << PCCONFIG_ACCESSTIME_SHIFT)) ;

    return ulSMC;    
}




VOID CPcmciaBusBridge::InitSocketNoCard( void)
{
    DEBUGMSG(1,(TEXT("++InitSocket")));

    //
    // I believe all that is needed here is to initialize the GPIO registers
    // so that a card can be detected. Only GPIO F is used and GPIOF 
    // is exclusively used for PCMCIA so there is no need to call
    // the system.
    //

    //
    // All GPIO pins are inputs.
    //
    *GPIO_PFDDR = 0;
    *GPIO_PFDR  = 0;        

    //
    // Temporarily disable all PCMCIA interrupts.
    //
    *GPIO_INTENF    = 0;

    //
    // Acknowlege any pending edge triggered PCMCIA interrupts.
    //
    *GPIO_FEOI      = 0xFF;
    
    //
    // We want to make the  GPIOF_PCMCIA_IRQ pin level triggered.
    // We don't care about any of the other bits in the register.
    //
    *GPIO_FINTTYPE1 = 0;
    
    //
    // We want the GPIOF_PCMCIA to be triggered high.
    //
    //*GPIO_FINTTYPE2  = GPIOF_PCMCIA_IRQ;

    //
    // We want the GPIOF_PCMCIA to be triggered low.
    //
    *GPIO_FINTTYPE2 = 0;
    
    //
    // Enable the interrupt.
    //
    *GPIO_INTENF    = GPIOF_PCMCIA_CD1 | GPIOF_PCMCIA_CD2| GPIOF_PCMCIA_IRQ;

    //
    // Setup the PCMCIA controller.
    //
    *SMC_PCCONFIG_ATT1  =   PCCONFIG_ADDRESSTIME_MASK |
                            PCCONFIG_HOLDTIME_MASK    |
                            PCCONFIG_ACCESSTIME_MASK  |
                            PCCONFIG_MW_8BIT;

    *SMC_PCCONFIG_MEM1  =   PCCONFIG_ADDRESSTIME_MASK |
                            PCCONFIG_HOLDTIME_MASK    |
                            PCCONFIG_ACCESSTIME_MASK  |
                            PCCONFIG_MW_8BIT;

    //
    // The Windows drivers never seem to set the access speed for the I/O
    // windows.  Since I/O has a fixed access speed we need to set it
    // initially.
    //
    *SMC_PCCONFIG_IO1   =   CalculatePcmciaTimings(0) |
                            PCCONFIG_MW_8BIT;

    *SMC_PCCONT         =   PCCONT_PC1EN | PCCONT_WEN1;


    DEBUGMSG (1,(TEXT("--InitSocket\n\r")));
}



BOOL CPcmciaBusBridge::SocketdRestCard( void ) 
{
	BOOL bStatus=true;
	ULONG	t, ulGPIOF;
    //   
	//ULONG	ulTemp;

	*SMC_PCCONT |= PCCONT_PC1EN | PCCONT_PC1RST | PCCONT_WEN1;

    Sleep(20);

    //
    // Clear the reset line.
    //    
     *SMC_PCCONT &= ~PCCONT_PC1RST| PCCONT_WEN1;

    Sleep(20);

    //
    // Allow the card 2 seconds to assert RDY
    //
    for (t = 0; t < PCMCIA_MAX_RDY_WAIT_TIME; t += PCMCIA_RDY_POLL_INT) 
    {
        ulGPIOF = *GPIO_PFDR;
        if (ulGPIOF & GPIOF_PCMCIA_IRQ) 
        {
            DEBUGMSG(ZONE_PDD,(TEXT("SocketdRestCard: Card  RDY after %dms\r\n"), t));
            break;
        }
        Sleep(PCMCIA_RDY_POLL_INT);
    }

    if (t >= PCMCIA_MAX_RDY_WAIT_TIME) 
    {
        DEBUGMSG(ZONE_PDD,(TEXT("SocketdRestCard: CARD NOT RDY AFTER %dms\r\n"),t));
		bStatus=FALSE;
    }
	Sleep(20);

	return bStatus;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -