Exynos 4412初始化外部地址总线

Exynos 4412外部地址总线与GPIO接口组Y(GPY)存在端口复用关系,其初始化需要操作以下寄存器:

  • GPY0CON0x11000000):配置片选脚(Xm0Csn)和读/写选通脚(EBI_OEn/EBI_WEn)功能复用。
  • GPY0PUD0x11000128):配置片选脚(Xm0Csn)和读/写选通脚(EBI_OEn/EBI_WEn)上下拉。
  • GPY1CON0x11000140):配置数据就绪脚(EBI_DATA_RDn)、WAIT信号输入脚(SROM_WAITn)、字节模式操作选通脚(EBI_BEn)功能复用。
  • GPY1PUD0x11000148):配置数据就绪脚(EBI_DATA_RDn)、WAIT信号输入脚(SROM_WAITn)、字节模式操作选通脚(EBI_BEn)上下拉。
  • GPY2CON0x11000160):配置NAND Flash相关脚功能复用。
  • GPY2PUD0x11000168):配置NAND Flash相关脚上下拉。
  • GPY3CON0x11000180):配置低位地址线(ADDR[0..7])脚功能复用。
  • GPY3PUD0x11000188):配置低位地址线(ADDR[0..7])脚脚上下拉。
  • GPY4CON0x110001A0):配置高位地址线(ADDR[8..15])脚脚功能复用。
  • GPY4PUD0x110001A8):配置高位地址线(ADDR[8..15])脚脚上下拉。
  • GPY5CON0x110001C0):配置低位数据线(DATA[0..7])脚功能复用。
  • GPY5PUD0x110001C8):配置低位数据线(DATA[0..7])脚上下拉。
  • GPY6CON0x110001E0):配置高位数据线(DATA[8..15])脚功能复用。
  • GPY6PUD0x110001E8):配置高位数据线(DATA[8..15])脚上下拉。

ARM汇编代码

例中,外部设备的片选脚位于Xm0Cs1(GPY0_1),模式为SROM。

参考自https://blog.csdn.net/u011583798/article/details/70215739

/* CSn, WE, OE*/
ldr  r0, =0x11000120 //GPY0CON
ldr  r1, =0x00222222 //SROM_CSn, EBI_OEn, EBI_WEn
str  r1, [r0]

/* BE, WAIT, RD */
ldr  r0, =0x11000140 //GPY1CON
ldr  r1, =0x00002222 //EBI
str  r1, [r0]

/* ADDR[0-7], pull up */
ldr  r0, =0x11000180 //GPY3CON
ldr  r1, =0x22222222 //EBI_ADDR
str  r1, [r0]
ldr  r0, =0x11000188 //GPY3PUD
ldr  r1, =0x0000FFFF //PULL_UP
str  r1, [r0]

/* DATA[0-7], pull up */
ldr  r0, =0x110001C0 //GPY5CON
ldr  r1, =0x22222222 //EBI_DATA
str  r1, [r0]
ldr  r0, =0x110001C8 //GPY5PUD
ldr  r1, =0x0000FFFF //PULL_UP
str  r1, [r0]

/* DATA[8-15], pull up */
ldr  r0, =0x110001E0 //GPY6CON
ldr  r1, =0x22222222 //EBI_DATA
str  r1, [r0]
ldr  r0, =0x110001E8 //GPY6PUD
ldr  r1, =0x0000FFFF //PULL_UP
str  r1, [r0]

/* SROM BANK 1 */
ldr  r0, =0x12570000 //SROM_BW
ldr  r1, [r0]
orr  r1, r1, #0xF0 //视情况改变SROM_BW寄存器的值
str  r1, [r0]

ldr  r0, =0x12570008 //SROM_BC1
ldr  r1, =SROM_BC1_VAL //视情况改变SROM_BCn寄存器的值
str  r1, [r0]

C代码

例中,外部设备的片选脚位于Xm0Cs1(GPY0_1),模式为SROM。

/* Main header files */
#include <linux/init.h>
#include <linux/module.h>
/* Useful header files */
#include <linux/kernel.h>
#include <linux/fs.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <mach/regs-gpio.h>
#include <asm/io.h>
#include <linux/regulator/consumer.h>
#include <linux/delay.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/uaccess.h>
/* Interrupt-related header files */
#include <linux/interrupt.h>
#include <linux/irq.h>
/* Library to generate random numbers */
#include <linux/random.h>
/* Spin-Lock, for we need it in Interrupt Handlers, we can't use Mutex */
#include <linux/spinlock.h> 
 
/* DEFINES */
//DBGPRINT() is used to print debug messages, comment #define IS_IN_DEBUG to disable them
#define IS_IN_DEBUG
#ifdef IS_IN_DEBUG
#define DBGPRINT(sInfo...) printk(KERN_INFO "UltrasoundDetectorDriver: " sInfo)
#else
#define DBGPRINT(sInfo...)
#endif
//printk() in different levels
#define NFOPRINT(sInfo...) printk(KERN_INFO "UltrasoundDetectorDriver - Info: " sInfo)
#define WRNPRINT(sInfo...) printk(KERN_WARNING "UltrasoundDetectorDriver - Warning: " sInfo)
#define ERRPRINT(sInfo...) printk(KERN_ERR "UltrasoundDetectorDriver - Error: " sInfo)
 
//External Device Memory Mapping
#define MEM_MAPPING_BASE_ADDR 0x05000000 //Base address for ioremap, we use Bank1 of SMC, whose address range is 0x05000000 to 0x05FFFFFF
#define MEM_MAPPING_SIZE_BYTE 4096 //Size for ioremap
#define MEM_MAPPING_NAME "UltSndDev" //Name of requested memory region
#define CHIP_SELECT_GPIO_LABEL EXYNOS4_GPY0(1) //Chip select pin label
#define CHIP_SELECT_GPIO_NAME "CHIP_SELECT_XM0CS1" //Chip select pin name
//EBI Related GPIOs
#define EBI_WEN_GPIO_LABEL EXYNOS4_GPY0(5) //nWE pin label
#define EBI_OEN_GPIO_LABEL EXYNOS4_GPY0(4) //nOE pin label
#define EBI_GPY1CON_START EXYNOS4_GPY1(0) //GPY1CON start
#define EBI_GPY1CON_END EXYNOS4_GPY1(3) //GPY1CON end
#define EBI_GPY1CON_PINCOUNT 4 //Pin count
#define EBI_ADDRLOW_START EXYNOS4_GPY3(0) //GPY3CON start (ADDR[0..7])
#define EBI_ADDRLOW_END EXYNOS4_GPY3(7) //GPY3CON end
#define EBI_ADDRLOW_PINCOUNT 8 //Pin count
#define EBI_ADDRHIGH_START EXYNOS4_GPY4(0) //GPY3CON start (ADDR[8..15])
#define EBI_ADDRHIGH_END EXYNOS4_GPY4(7) //GPY3CON end
#define EBI_ADDRHIGH_PINCOUNT 8 //Pin count
#define EBI_DATALOW_START EXYNOS4_GPY5(0) //GPY5CON start (DATA[0..7])
#define EBI_DATALOW_END EXYNOS4_GPY5(7) //GPY5CON end
#define EBI_DATALOW_PINCOUNT 8 //Pin count
#define EBI_DATAHIGH_START EXYNOS4_GPY6(0) //GPY6CON start (DATA[8..15])
#define EBI_DATAHIGH_END EXYNOS4_GPY6(7) //GPY6CON end
#define EBI_DATAHIGH_PINCOUNT 8 //Pin count
//SROM_BXx Registers
#define S3C_REGISTER_SROM_BASE_ADDR 0x12570000 //Base address of register "SROM_BW" and "SROM_BCn", we will reconfigure SROM_BW[4..7] and SROM_BC1[31..0]
#define S3C_REGISTER_SROM_SIZE_BYTE 0x20 //Size of SROM_BW and SROM_BCn, 4 Bytes (32Bit) x 5
#define S3C_REGISTER_SROM_NAME "SROM_BXx" //Name of requested memory region
#define S3C_REGISTER_SROM_BW_ADDR_OFFSET 0x00 //Address offset of SROM_BW
#define S3C_REGISTER_SROM_BC0_ADDR_OFFSET 0x04 //Address offset of SROM_BC0
#define S3C_REGISTER_SROM_BC1_ADDR_OFFSET 0x08 //Address offset of SROM_BC1
#define S3C_REGISTER_SROM_BC2_ADDR_OFFSET 0x0C //Address offset of SROM_BC2
#define S3C_REGISTER_SROM_BC3_ADDR_OFFSET 0x10 //Address offset of SROM_BC3
#define S3C_REGISTER_SROM_BW_CONFIG_BITS 0x00000010 //Set SROM_BW[4..7] to binary value 0001 (Does not use UB/LB, Disables WAIT, Half-word base address, 16bit data bus width). SROM_BW=SROM_BW | S3C_REGISTER_SROM_BW_CONFIG_BITS,视情况改变
#define S3C_REGISTER_SROM_BC1_CONFIG_BITS 0x220F2200 //Tacs=2, Tcos=2, Tacc=16, Tcoh=2, Tcah=2, Tacp=0 (Cycles). SROM_BC1=SROM_BC1 | S3C_REGISTER_SROM_BC1_CONFIG_BITS,视情况改变
 
void InitializeEBI(){
    //Config EBI and IORemap
    //Config SROM_BXx Registers
    request_region(S3C_REGISTER_SROM_BASE_ADDR, S3C_REGISTER_SROM_SIZE_BYTE, S3C_REGISTER_SROM_NAME);
    lpSromRegistersBaseAddress = ioremap(S3C_REGISTER_SROM_BASE_ADDR, S3C_REGISTER_SROM_SIZE_BYTE);
    lpSromRegistersResource = request_mem_region(S3C_REGISTER_SROM_BASE_ADDR, S3C_REGISTER_SROM_SIZE_BYTE, S3C_REGISTER_SROM_NAME);
    if (lpSromRegistersBaseAddress){
        NFOPRINT("SFR SROM_BW and SROM_BCn mapped to virtual address 0x%x.\n", lpSromRegistersBaseAddress);
 
        iSromBw=__raw_readl(lpSromRegistersBaseAddress);
        DBGPRINT("SFR SROM_BW=0x%x.\n", iSromBw);
        iSromBw=iSromBw | S3C_REGISTER_SROM_BW_CONFIG_BITS;
        DBGPRINT("Writing SROM_BW with 0x%x inorder to config Xm0Cs1.\n", iSromBw);
        __raw_writel(iSromBw, lpSromRegistersBaseAddress);
        iSromBw=__raw_readl(lpSromRegistersBaseAddress);
        DBGPRINT("SFR SROM_BW=0x%x.\n", iSromBw);
 
        iSromBc1=__raw_readl(lpSromRegistersBaseAddress + S3C_REGISTER_SROM_BC1_ADDR_OFFSET);
        DBGPRINT("SFR SROM_BC1=0x%x.\n", iSromBc1);
        //iSromBc1=iSromBc1 | S3C_REGISTER_SROM_BC1_CONFIG_BITS;
        DBGPRINT("Writing SROM_BC1 with 0x%x inorder to config Xm0Cs1.\n", iSromBc1);
        __raw_writel(iSromBc1, lpSromRegistersBaseAddress + S3C_REGISTER_SROM_BC1_ADDR_OFFSET);
        iSromBc1=__raw_readl(lpSromRegistersBaseAddress + S3C_REGISTER_SROM_BC1_ADDR_OFFSET);
        DBGPRINT("SFR SROM_BC1=0x%x.\n", iSromBc1);
    }
    else{
        WRNPRINT("Failed to map SFR SROM_BW and SROM_BCn. The remap of external device at Xm0Cs1 may not success.\n");
    }
    //Map External Device
    //Request GPIOs
    int iCsResult=0;
    iCsResult=gpio_request(CHIP_SELECT_GPIO_LABEL, CHIP_SELECT_GPIO_NAME);
    if (0==iCsResult){
        //Config EBI
        //GPY0
        s3c_gpio_cfgpin(CHIP_SELECT_GPIO_LABEL, S3C_GPIO_SFN(0x2)); //Set GPY0CON[1] to 0x2 (SROM_CSn[1])
        s3c_gpio_setpull(CHIP_SELECT_GPIO_LABEL, S3C_GPIO_PULL_UP); //Set GPY0PUD[1] to PULL_UP
        s5p_gpio_set_drvstr(CHIP_SELECT_GPIO_LABEL, S5P_GPIO_DRVSTR_LV4); //Set drive strength to max
        s3c_gpio_cfgpin(EBI_WEN_GPIO_LABEL, S3C_GPIO_SFN(0x2)); //Set GPY0CON[5] to 0x2 (EBI_WEn)
        s3c_gpio_setpull(EBI_WEN_GPIO_LABEL, S3C_GPIO_PULL_UP); //Set GPY0PUD[5] to PULL_UP
        s3c_gpio_cfgpin(EBI_OEN_GPIO_LABEL, S3C_GPIO_SFN(0x2)); //Set GPY0CON[4] to 0x2 (EBI_OEn)
        s3c_gpio_setpull(EBI_OEN_GPIO_LABEL, S3C_GPIO_PULL_UP); //Set GPY0PUD[4] to PULL_UP
        //GPY1
        s3c_gpio_cfgall_range(EBI_GPY1CON_START, EBI_GPY1CON_PINCOUNT, S3C_GPIO_SFN(0x2), S3C_GPIO_PULL_UP); //Set GPY1CON to 0x00002222 (EBI_DATA_RDn, SROM_WAITn, EBI_BEn[1], EBI_BEn[0])
        //ADDR
        s3c_gpio_cfgall_range(EBI_ADDRLOW_START, EBI_ADDRLOW_PINCOUNT, S3C_GPIO_SFN(0x2), S3C_GPIO_PULL_UP); //set GPY3CON to 0x22222222 (EBI_ADDR[7..0]), and set GPY3PUD to 0x0000FFFF (PULL_UP)
        //s3c_gpio_cfgall_range(EBI_ADDRHIGH_START, EBI_ADDRHIGH_PINCOUNT, S3C_GPIO_SFN(0x2), S3C_GPIO_PULL_UP); //set GPY4CON to 0x22222222 (EBI_ADDR[15..8]), and set GPY4PUD to 0x0000FFFF (PULL_UP)
        //DATA
        s3c_gpio_cfgall_range(EBI_DATALOW_START, EBI_DATALOW_PINCOUNT, S3C_GPIO_SFN(0x2), S3C_GPIO_PULL_UP);
        s3c_gpio_cfgall_range(EBI_DATAHIGH_START, EBI_DATAHIGH_PINCOUNT, S3C_GPIO_SFN(0x2), S3C_GPIO_PULL_UP); //Set GPY5CON & GPY6CON to 0x22222222 (EBI_DATA), and set GPY5PUD & GPY6PUD to 0x0000FFFF (PULL_UP)
 
        //IORemap
        request_region(MEM_MAPPING_BASE_ADDR, MEM_MAPPING_SIZE_BYTE, MEM_MAPPING_NAME);
        lpIoResource = request_mem_region(MEM_MAPPING_BASE_ADDR, MEM_MAPPING_SIZE_BYTE, MEM_MAPPING_NAME);
        lpExternalDeviceBaseAddress = ioremap(MEM_MAPPING_BASE_ADDR, MEM_MAPPING_SIZE_BYTE);
        DBGPRINT("Mapping external device to virtual address 0x%x, Size=%d Bytes.\n", lpExternalDeviceBaseAddress, MEM_MAPPING_SIZE_BYTE);
        if (!lpExternalDeviceBaseAddress){
            WRNPRINT("Failed to map external device.\n");
        }
        else{
            NFOPRINT("External device mapped to virtual address 0x%x.\n", lpExternalDeviceBaseAddress);
        }
    }
    else{
        WRNPRINT("Request GPIO %d failed with return code %d. Unnable to remap external device.\n", CHIP_SELECT_GPIO_LABEL, iCsResult);
    }
}
it
除非特别注明,本页内容采用以下授权方式: Creative Commons Attribution-ShareAlike 3.0 License