pcidriver.c

来自「source code of armboot for s3c4510」· C语言 代码 · 共 222 行

C
222
字号
/*
 * File:    pcidriver.c
 *
 * Purpose: PCI bus access
 */


#if !defined(__PLATFORM_H__)
#include "platform.h"
#endif
#if !defined(__PCIDRIVER_H__)
#include "pcidriver.h"
#endif




/*---------------------  Static Definitions  ------------------------*/

/*---------------------  Static Types  ------------------------------*/

/*---------------------  Static Macros  -----------------------------*/

/*---------------------  Static Classes  ----------------------------*/

/*---------------------  Static Variables  --------------------------*/

/*---------------------  Static Functions  --------------------------*/
static UINT32 s_u32MakeBfd2CfgAddr(UINT32 bus, UINT32 device, UINT32 function, UINT32 offset);

/*---------------------  Export Variables  --------------------------*/




void PCIBDG_Initialize(void)
{
    // use internal arbitor, should do this before PCICON_CONFIG_DONE had been set
    ASIC_PCI_PCICON |= PCIARBITOR_INT;

    // Internal Clock, PCI Reset, Pull-up,
    // Enable PCI Clock output for the Slot3
    ASIC_PCI_PCIDIAG0 &= ~(PCICLK_EXT | PCICLK_DC3 | PCIRESET_EXT | PCIPULLUP_EXT);
    // set PCI logic & bus clock
    ASIC_PCI_PCIRCC |= PCICLK_33M;

    // turn off mask, will assert PCI host logic & bus reset
    ASIC_PCI_PCIRCC &= ~PCIRESETCLK_MASK;
    // delay for PCI bus reset
    PLAT_vDelayLoop(1);
    // Deassert PCI host logic & bus reset
    ASIC_PCI_PCIRCC |= PCILOG_RESET;
    ASIC_PCI_PCIRCC |= PCIBUS_RESET;
    // to wait for exerciser to ready
    PLAT_vDelayLoop(10);

    // for PCI address translate to AHB address when device is in master mode

    // Space(0x0 to 0x0100_0000-1), 16MB
    ASIC_PCI_PCIBAM0 = (~ASIC_DRAM_SIZE) + 1;
    ASIC_PCI_PCIBATPA0 = 0;

    ASIC_PCI_PCIHSC |= PCI_PCIHSC_BME | PCI_PCIHSC_MWI | PCI_PCIHSC_PEE;

    // Memory base address register 0/1 and IO for ARM9 use
    ASIC_PCI_PCIHBAR0 = 0;
    ASIC_PCI_PCIHBAR1 = 0x00080000;
    ASIC_PCI_PCIHBAR2 = 0;

    ASIC_PCI_PCIHSC |= PCIHSC_STATUS_ALL;

    ASIC_PCI_PCICON |= PCICON_CONFIG_DONE | PCICON_SYSTEMREAD_READY;
    ASIC_PCI_PCICON &= ~PCICON_MMP;       //Memory Burst Read Disable(Burst Read decrease its performance).

    // disable doorbell bit
    ASIC_PCI_PCIBELPA &= 0x7FFFFFFF;

#if defined(__BIG_ENDIAN)
    ASIC_PCI_PCISWAP |= (PCISWAP_TRW | PCISWAP_TTW);    //4-byte swap
#endif
}

UINT8 PCICFG_Read8(UINT32 bus, UINT32 device, UINT32 function, UINT32 offset)
{
    UINT8*  pAddress;

    /* generate the address of correct configuration space */
    pAddress = (UINT8*) (s_u32MakeBfd2CfgAddr(bus, device, function, offset));
    return (*pAddress);
}


UINT16 PCICFG_Read16(UINT32 bus, UINT32 device, UINT32 function, UINT32 offset)
{
    UINT16* pAddress;

    /* generate the address of correct configuration space */
    pAddress = (UINT16*) (s_u32MakeBfd2CfgAddr(bus, device, function, offset));
    /* now that we have valid params, go read the config space data */
    return (*pAddress);
}


UINT32 PCICFG_Read32(UINT32 bus, UINT32 device, UINT32 function, UINT32 offset)
{
    UINT32* pAddress;

    /* generate the address of correct configuration space */
    pAddress = (UINT32*) (s_u32MakeBfd2CfgAddr(bus, device, function, offset));
    return (*pAddress);
}


void PCICFG_Write8(UINT32 bus, UINT32 device, UINT32 function, UINT32 offset, UINT32 data)
{
    UINT8*  pAddress;

    /* generate the address of correct configuration space */
    pAddress = (UINT8*) (s_u32MakeBfd2CfgAddr(bus, device, function, offset));
    *pAddress = (UINT8)data;
}


void PCICFG_Write16(UINT32 bus, UINT32 device, UINT32 function, UINT32 offset, UINT32 data)
{
    UINT16* pAddress;

    /* generate the address of correct configuration space */
    pAddress = (UINT16*) (s_u32MakeBfd2CfgAddr(bus, device, function, offset));
    *pAddress = (UINT16)data;
}


void PCICFG_Write32(UINT32 bus, UINT32 device, UINT32 function, UINT32 offset, UINT32 data)
{
    UINT32* pAddress;

    /* generate the address of correct configuration space */
    pAddress = (UINT32*) (s_u32MakeBfd2CfgAddr(bus, device, function, offset));
    *pAddress = (UINT32)data;
}


/*============================================================================
 *
 * parameters:  bus = which bus
 *              device = which device
 *              function = which function
 *      offset = configuration space register we are interested in
 *
 * description: this routine will generate a platform dependant config
 *      address.
 *
 * calls:   none
 *
 * returns: configuration address to play on the PCI bus
 *
 * To generate the appropriate PCI configuration cycles in the PCI
 * configuration address space, you make AHB address with the following pattern
 *
 * PCI configuration cycles look like this:
 *
 * Type 0:  area0: 0x28000000 - 0x2800A7FF, Other space,0x2800A800 - 0x29FFFFFF, are not used
 *          area1: 0x38000000 - 0x3800A7FF --> Not used
 *
 *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
 *  3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0|
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 *  31:28   Area selection  : 0010b(PCI space area0)
 *  27:25   Access space    : 100b(Type0)
 *  24:16   fixed           : 0 (fixed by 0)
 *  15:11   Device select   : 00000b(AD[11]),00001b(AD[12]),00010b(AD[13]), ... ,10100b(AD[31])
 *  10:8    Function number :
 *   7:2    Register number
 *
 * Type 1:  area0: 0x2A000000 - 0x2AFFFFFF, Other space,0x2B000000 - 0x2BFFFFFF, are not used
 *          area1: 0x3A000000 - 0x3BFFFFFF --> Not used
 *
 *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
 *  3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 *  31:28   Area selection  : 0010b(PCI space area0), 0011b(PCI space area1)
 *  27:25   Access space    : 101b(Type1)
 *  24      fixed           : 0
 *  23:16   bus number (8 bits = 128 possible buses)
 *  15:11   Device number (5 bits)
 *  10:8    function number
 *   7:2    register number
 *
 */
static UINT32 s_u32MakeBfd2CfgAddr(UINT32 bus, UINT32 device, UINT32 function, UINT32 offset)
{
    UINT32 address;

    if (bus == 0) {
        if (device != 0) {
            /* Bus0, so it needs a type 0 config cycle */
            /* build the PCI configuration "address" with one-hot in A31-A11 */
            address = AHB_2_PCI_CFG0(device, function, offset);
        }
        else {
            address = 0xf0110000;
            address |= offset & 0xff;
        }
    }
    else {       /* bus !=0 */
        /* Not Bus0, so need a type 1 config cycle */
        /* A31-A24 are don't care (so clear to 0) */
        address = AHB_2_PCI_CFG1(bus, device, function, offset);
    }

    return address;
}


⌨️ 快捷键说明

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