Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1478183
  • 博文数量: 842
  • 博客积分: 12411
  • 博客等级: 上将
  • 技术积分: 5772
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-14 14:43
文章分类

全部博文(842)

文章存档

2013年(157)

2012年(685)

分类:

2012-05-08 13:26:43

原文地址:Linux-IO内存-静态映射 作者:Cheney-Xu

Linux-IO内存-静态映射

 

通常来说,BSP需要提供芯片级驱动,并要为板级驱动提供一些服务,在为具体芯片移植linux内核时,通常都会建立芯片级外设I/O内存物理地址到虚拟地址的静态映射,这通常是通过板文件中的MACHINE_START宏中的map_io函数来实现的,map_io函数中通常通过调用

iotable_init函数来建立页映射关系,如:iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));这种静态映射关系通常通过map_desc结构体来描述,map_desc结构定义如下:

struct map_desc {

    unsigned long virtual;

    unsigned long physical;

    unsigned long length;

    unsigned int type;

};    

#define MT_DEVICE    0

#define MT_CACHECLEAN       1

#define MT_MINICLEAN     2

#define MT_LOW_VECTORS      3

#define MT_HIGH_VECTORS     4

#define MT_MEMORY    5

#define MT_ROM           6

#define MT_IXP2000_DEVICE   7

我们来看一下BSP怎样使用map_desc

static struct map_desc s3c_iodesc[] __initdata = {

    IODESC_ENT(GPIO),

    IODESC_ENT(IRQ),

    IODESC_ENT(MEMCTRL),

    IODESC_ENT(UART)

};

其中IODESC_ENT定义如下(##为连接符,它会##两边的字符连接起来):


 

#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, S3C2410_PA_##x, S3C24XX_SZ_##x, MT_DEVICE }

IODESC_ENT(GPIO),展开如下:

{

(unsigned long)S3C24XX_VA_GPIO,

S3C2410_PA_GPIO,

S3C24XX_SZ_GPIO,

        MT_DEVICE

}

 

其中include/asm-arm/arch-s3c2410/map.h中定义了外设IO内存中要使用的宏

这样便把芯片级外设IO内存物理地址与虚拟地址连接起来了

GPIO的驱动程序,通常会这样使用GPIO

void __init smdk2440_machine_init(void)

{

    /* Configure the LEDs (even if we have no LED support)*/

    s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);

    s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);

    s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);

    s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);

 

    s3c2410_gpio_setpin(S3C2410_GPF4, 0);

    s3c2410_gpio_setpin(S3C2410_GPF5, 0);

    s3c2410_gpio_setpin(S3C2410_GPF6, 0);

    s3c2410_gpio_setpin(S3C2410_GPF7, 0);

    s3c2410_pm_init();

}

其中S3C2410_GPF4等定义如下:

#define S3C2410_GPF4        S3C2410_GPIONO(S3C2410_GPIO_BANKF, 4)

#define S3C2410_GPF4_INP    (0x00 << 8)

#define S3C2410_GPF4_OUTP   (0x01 << 8)

#define S3C2410_GPF4_EINT4  (0x02 << 8)

 

#define S3C2410_GPF5        S3C2410_GPIONO(S3C2410_GPIO_BANKF, 5)

#define S3C2410_GPF5_INP    (0x00 << 10)

#define S3C2410_GPF5_OUTP   (0x01 << 10)

#define S3C2410_GPF5_EINT5  (0x02 << 10)

 

#define S3C2410_GPF6        S3C2410_GPIONO(S3C2410_GPIO_BANKF, 6)

#define S3C2410_GPF6_INP    (0x00 << 12)

#define S3C2410_GPF6_OUTP   (0x01 << 12)

#define S3C2410_GPF6_EINT6  (0x02 << 12)

 

#define S3C2410_GPF7        S3C2410_GPIONO(S3C2410_GPIO_BANKF, 7)

#define S3C2410_GPF7_INP    (0x00 << 14)

#define S3C2410_GPF7_OUTP   (0x01 << 14)

#define S3C2410_GPF7_EINT7  (0x02 << 14)

其中S3C2410_GPIONO等定义如下:

#define S3C2410_GPIONO(bank,offset) ((bank) + (offset))

#define S3C2410_GPIO_BANKA   (32*0)

#define S3C2410_GPIO_BANKB   (32*1)

#define S3C2410_GPIO_BANKC   (32*2)

#define S3C2410_GPIO_BANKD   (32*3)

#define S3C2410_GPIO_BANKE   (32*4)

#define S3C2410_GPIO_BANKF   (32*5)

#define S3C2410_GPIO_BANKG   (32*6)

#define S3C2410_GPIO_BANKH   (32*7)

所以,算出的S3C2410_GPF4 =S3C2410_GPIONO(S3C2410_GPIO_BANKF, 4)=S3C2410_GPIONO(32*5, 4)=32*5+ 4

我们现来看一下s3c2410_gpio_cfgpins3c2410_gpio_setpin函数

s3c2410_gpio_cfgpin函数定义如下

void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)

{

    void __iomem *base = S3C2410_GPIO_BASE(pin);

    unsigned long mask;

    unsigned long con;

    unsigned long flags;

 

    if (pin < S3C2410_GPIO_BANKB) {

       mask = 1 << S3C2410_GPIO_OFFSET(pin);

    } else {

       mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;

    }

 

    local_irq_save(flags);

 

    con  = __raw_readl(base + 0x00);

    con &= ~mask;

    con |= function;

 

    __raw_writel(con, base + 0x00);

 

    local_irq_restore(flags);

}

s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);

便是s3c2410_gpio_cfgpin32*5+ 40x01 << 8

#define S3C2410_GPIO_BASE(pin)   ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)

#define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)

#define S3C24XX_VA_GPIO     S3C2410_ADDR(0x00E00000)

#define S3C2400_PA_GPIO     (0x15600000)

#define S3C2410_PA_GPIO     (0x56000000)

#define S3C24XX_SZ_GPIO     SZ_1M

*base=((((32*5+ 4) & ~31) >> 1) + S3C24XX_VA_GPIO)=((((32*5+ 4) & ~31) >> 1) + S3C2410_ADDR(0x00E00000))

其中S3C2410_ADDR定义如

 

#ifndef __ASSEMBLY__

#define S3C2410_ADDR(x)    ((void __iomem *)0xF0000000 + (x))

#else

#define S3C2410_ADDR(x)    (0xF0000000 + (x))

#endif

因此*base= ((((32*5+ 4) & ~31) >> 1) + 0xF0E00000)

GPIOF的控制寄存器物理地址如下:

 

 

阅读(328) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~