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。

/* PLATFORM SUPPORT :: SROM ACCESS :: SAMSUNG :: EXYNOS 4412
 * 
 * This header file contains code that used to configure Samsung Exynos 4412 SoC's External Bus Interface (EBI) for SROM access.
 * Including register configurations and GPIO pin configurations.
 *
 * GPIO constants and functions are defined in the following location(s) in iTop-4412's Linux Kernel source:
 * - arch\arm\plat-samsung\include\plat\gpio-cfg.h
 * 
 */
 
#ifndef _PLATFORMSUPPORT_SROMACCESS_SAMSUNG_EXYNOS4412_H
#define _PLATFORMSUPPORT_SROMACCESS_SAMSUNG_EXYNOS4412_H
 
/* Main header files */
#include <linux/init.h>
#include <linux/module.h>
/* Useful header files */
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/delay.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <asm/io.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>
/* Timers */
#include <linux/timer.h>
#include <linux/jiffies.h>
/* Platform-related header files */
#include <mach/gpio.h>
#include <mach/regs-gpio.h>
#include <plat/gpio-cfg.h>
/* Local header files */
#include "ultsnddrv4412.h"
#include "MathFunctions.h"
 
/* Defines that EBI configurations are requested */
#define EBI_CONFIG_REQUESTED
 
/* External Bus Interface (EBI) Configurations */
#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 0x000F0000 //Use short-timed reading timing for restructured FPGA, Tacs=0, Tcos=0, Tacc=16, Tcoh=0, Tcah=0, Tacp=0 (Cycles, 1 Cycle = 5 ns). SROM_BC1=SROM_BC1 | S3C_REGISTER_SROM_BC1_CONFIG_BITS
//#define S3C_REGISTER_SROM_BC1_CONFIG_BITS 0xFF1FFF00 //Use long-timed reading timing for original FPGA, Tacs=15, Tcos=15, Tacc=32, Tcoh=15, Tcah=15, Tacp=0 (Cycles, 1 Cycle = 5 ns). SROM_BC1=SROM_BC1 | S3C_REGISTER_SROM_BC1_CONFIG_BITS
 
/* Address of SROM_BW and SROM_BC1 */
static void * lpSromRegistersBaseAddress = NULL; //Remapped address for SROM_BW
static struct resource * lpSromRegistersResource = NULL; //Memory region resource
static unsigned int iSromBw; //Value of SROM_BW
static unsigned int iSromBc1; //Value of SROM_BC1
 
/* Configure SROM access on initializing */
//Returns 0 if operation is success
static int InitConfigureSROMAccess(){
    //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");
    }
    //Request GPIOs for external device mapping
    int iCsResult=0;
    iCsResult=gpio_request(CHIP_SELECT_GPIO_LABEL, CHIP_SELECT_GPIO_NAME);
    if (0==iCsResult){
        //Config EBI
        int iEBIConfigResult=0;
        //GPY0
        iEBIConfigResult=s3c_gpio_cfgpin(CHIP_SELECT_GPIO_LABEL, S3C_GPIO_SFN(0x2)); //Set GPY0CON[1] to 0x2 (SROM_CSn[1])
        if (iEBIConfigResult != 0){
            WRNPRINT("Failed to config GPY0_1 (Xm0Cs1), Error %d. The remap of external device at Xm0Cs1 may not success.\n", iEBIConfigResult);
        }
        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
        iEBIConfigResult=s3c_gpio_cfgpin(EBI_WEN_GPIO_LABEL, S3C_GPIO_SFN(0x2)); //Set GPY0CON[5] to 0x2 (EBI_WEn)
        if (iEBIConfigResult != 0){
            WRNPRINT("Failed to config GPY0_5 (Xm0WEn), Error %d. The remap of external device at Xm0Cs1 may not success.\n", iEBIConfigResult);
        }
        s3c_gpio_setpull(EBI_WEN_GPIO_LABEL, S3C_GPIO_PULL_UP); //Set GPY0PUD[5] to PULL_UP
        iEBIConfigResult=s3c_gpio_cfgpin(EBI_OEN_GPIO_LABEL, S3C_GPIO_SFN(0x2)); //Set GPY0CON[4] to 0x2 (EBI_OEn)
        if (iEBIConfigResult != 0){
            WRNPRINT("Failed to config GPY0_4 (Xm0OEn), Error %d. The remap of external device at Xm0Cs1 may not success.\n", iEBIConfigResult);
        }
        s3c_gpio_setpull(EBI_OEN_GPIO_LABEL, S3C_GPIO_PULL_UP); //Set GPY0PUD[4] to PULL_UP
        //GPY1
        iEBIConfigResult=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])
        if (iEBIConfigResult != 0){
            WRNPRINT("Failed to config GPY1, Error %d. The remap of external device at Xm0Cs1 may not success.\n", iEBIConfigResult);
        }
        //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)
        if (iEBIConfigResult != 0){
            WRNPRINT("Failed to config GPY3 (Xm0ADDR[0..7]), Error %d. The remap of external device at Xm0Cs1 may not success.\n", iEBIConfigResult);
        }
        //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)
        //if (iEBIConfigResult != 0){
        //    WRNPRINT("Failed to config GPY4 (Xm0ADDR[8..15]), Error %d. The remap of external device at Xm0Cs1 may not success.\n", iEBIConfigResult);
        //}
        //DATA
        s3c_gpio_cfgall_range(EBI_DATALOW_START, EBI_DATALOW_PINCOUNT, S3C_GPIO_SFN(0x2), S3C_GPIO_PULL_UP);
        if (iEBIConfigResult != 0){
            WRNPRINT("Failed to config GPY5 (Xm0DATA[0..7]), Error %d. The remap of external device at Xm0Cs1 may not success.\n", iEBIConfigResult);
        }
        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)
        if (iEBIConfigResult != 0){
            WRNPRINT("Failed to config GPY6, Error %d. The remap of external device at Xm0Cs1 may not success.\n", iEBIConfigResult);
        }
 
        gpio_free(CHIP_SELECT_GPIO_LABEL);
        return 0;
    }
    else{
        WRNPRINT("Request GPIO %d failed with return code %d. Unnable to remap external device.\n", CHIP_SELECT_GPIO_LABEL, iCsResult);
        return iCsResult;
    }
}
 
/* Release SROM access on initializing */
static void ExitReleaseSROMAccess(){
    iounmap(lpSromRegistersBaseAddress);
    release_mem_region(lpSromRegistersResource, S3C_REGISTER_SROM_SIZE_BYTE);
    release_region(S3C_REGISTER_SROM_BASE_ADDR, S3C_REGISTER_SROM_SIZE_BYTE);
    return;
}
 
#endif
it
除非特别注明,本页内容采用以下授权方式: Creative Commons Attribution-ShareAlike 3.0 License