Chinaunix首页 | 论坛 | 博客
  • 博客访问: 290785
  • 博文数量: 25
  • 博客积分: 2480
  • 博客等级: 上尉
  • 技术积分: 365
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-27 11:27
个人简介

除了奋斗,我别无选择!

文章分类

全部博文(25)

文章存档

2012年(1)

2011年(22)

2010年(2)

分类: LINUX

2011-07-16 09:27:21

采用S3C2440处理器(和S3C2410区别不大),在其Linux源码中,和这个平台相关的代码主要在arch/arm/mach-s3c2410include/asm-arm/arch-s3c2410中,相关驱动在drivers目录中。

(1)   DM9000 网卡驱动

kernel-2.6.13/drivers/net/dm9000x.c

(2)   串口(包括三个串口驱动0,1,2,对应设备名/dev/tts/0,1,2)

kernel-2.6.13/drivers/serial/s3c2410.c

(3)   (3)实时时钟RTC 驱动

kernel-2.6.13/drivers/char/s3c2410-rtc.c

(4)   LED 驱动

kernel-2.6.13/drivers/char/qq2440_leds.c

(5)   按键驱动

kernel-2.6.13/drivers/char/qq2440_buttons.c

(6)   触摸屏驱动

kernel-2.6.13/drivers/input/touchscreen/s3c2410_ts.c

(7)   yaffs 文件系统源代码目录

kernel-2.6.13/fs/yaffs2

(8)   USB 鼠标、键盘源代码

kernel-2.6.13/drivers/ usb/input/hid-input.c

(9)   SD/MMC 卡驱动源代码目录(2.6.13 内核中仅支持2G 容量以内的SD )

kernel-2.6.13/drivers/mmc

(10)             Nand Flash 驱动

kernel-2.6.13/drivers/mtd/nand

(11)             UDA1341 音频驱动目录

kernel-2.6.13/ sound/oss/uda1341.c

kernel-2.6.13/ drivers/l3

(12)             LCD 驱动(包含3.5", 7", 8.4", 10.4", 12.4", 15"等大小的驱动)

kernel-2.6.13/drivers/video/s3c2410fb.c

(13)             优盘支持驱动

kernel-2.6.13/drivers/usb/storage

(14)             中星微USB 摄像头驱动

kernel-2.6.13/drivers/usb/media/gspca

1.S3C2410_GPB5是端口编号,定义在regs-gpio.h

#define S3C2410_GPIO_BANKB   (32*1)

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

#define S3C2410_GPB5         S3C2410_GPIONO(S3C2410_GPIO_BANKB, 5)

S3C2410共有130GPIO,分为9组(GPA~GPJ),每组最多可以有32个,每个GPIO2~4个可选功能,每组的控制寄存器空间有4个,例如对于GPB,有GPBCONGPBDATGPBUPReserved,分别是功能配置、数据缓存、上拉使能和保留。

上面的S3C2410_GPB5就是GPIO的编号,也就是在号码空间(0~32*9-1)中的位置,bank是分组的基号码,offset是组内偏移量。

2.S3C2410_GPB5_OUTP是端口功能,定义在regs-gpio.h

#define S3C2410_GPB5_INP     (0x00 << 10)

#define S3C2410_GPB5_OUTP    (0x01 << 10)

GPBCON的第1011两位用于配置GPB5的功能,00 = Input 01 = Output

3.S3C2410 GPIO的操作函数

hardware.h文件中有:

s3c2410_gpio_cfgpin     //配置端口的GPIO的功能

s3c2410_gpio_getcfg     //读取功能配置

s3c2410_gpio_pullup     //配置上拉电阻

s3c2410_modify_misccr //杂项配置

s3c2410_gpio_getirq      //给定端口,转换出IRQ

s3c2410_gpio_irqfilter    //配置IRQ过滤使能与否

s3c2410_gpio_setpin     //写数据到端口

s3c2410_gpio_getpin     //从端口读数据

这些函数的实现在gpio.h

void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)

{

void __iomem *base = S3C2410_GPIO_BASE(pin);

unsigned long offs = S3C2410_GPIO_OFFSET(pin);

unsigned long flags;

unsigned long dat;

local_irq_save(flags);

dat = __raw_readl(base + 0x04);

dat &= ~(1 << offs);

dat |= to << offs;

__raw_writel(dat, base + 0x04);

local_irq_restore(flags);

}

4.S3C2410_GPIO_BASES3C2410_GPIO_OFFSET也是在regs-gpio.h文件中定义

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

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

而在map.h中有:

#define S3C24XX_VA_GPIO    S3C2410_ADDR(0x00E00000) //虚拟地址S3C24XX_VA_GPIO= 0xF0E00000

#define S3C2400_PA_GPIO    (0x15600000)

#define S3C2410_PA_GPIO    (0x56000000) //GPACON 物理地址

#define S3C24XX_SZ_GPIO    SZ_1M //0x100000 = 1024 *1024

S3C2410_GPIO_BASE作用是:根据端口编号pin,算出端口所在组的虚拟基址。((pin) & ~31)是去掉pin当中小于等于31的零头(清05位),>>1的原因是每组GPIO中最多可以有32个端口,控制这些端口需要4个寄存器空间,4个寄存器空间就需要4*4=16个字节进行编址,32/16=2,右移一位刚好满足。也就是说,上一组端口和下一组端口的编号相差32,而控制寄存器的地址相差16(右移一位相当于除以2)

 

s3c2410_gpio_setpin()gpio.c

作用:设置相应GPIO口的值,

pin=S3C2410_GPB5 to=0 则:设置S3C2410_GPB5的输出值为0

pin=S3C2410_GPB5 to=1 则:设置S3C2410_GPB5的输出值为1

void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
{

void __iomem *base = S3C2410_GPIO_BASE(pin);

unsigned long offs = S3C2410_GPIO_OFFSET(pin);

 unsigned long flags;

 unsigned long dat;

local_irq_save(flags);

dat = __raw_readl(base + 0x04);

dat &= ~(1 << offs);

dat |= to << offs;

__raw_writel(dat, base + 0x04);

 local_irq_restore(flags);
}

EXPORT_SYMBOL(s3c2410_gpio_setpin);
??
说明:

1.

S3C2410_GPIO_BASE(pin)-------------

linux/include/asm/hardware/s3c2410/regs-gpio.h

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

S3C24XX_VA_GPIO------------

linux/include/asm-arm/arch-s3c2410/map.h

#define S3C24XX_VA_GPIO S3C2410_ADDR(0x00E00000)

----GPIO的虚拟偏移地址:0x00E00000

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

----所有寄存器的虚拟首地址:0xF0000000

则:

S3C24XX_VA_GPIO 0xF0E0 0000 ----GPIO的虚拟首地址

如:pin = S3C2410_GPB5

而在linux/include/asm/hardware/s3c2410/regs-gpio.h

#define S3C2410_GPB5 S3C2410_GPIONO(S3C2410_GPIO_BANKB, 5)

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

#define S3C2410_GPIO_BANKB (32*1)

则:

S3C2410_GPB5 321+537

由:

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

pin = S3C2410_GPB5 37

S3C24XX_VA_GPIO 0xF0E0 0000

则:

S3C2410_GPIO_BASE(S3C2410_GPB5) ((((S3C2410_GPB5) & ~31) >> 1) +0xF0E0 0000 )

S3C2410_GPIO_BASE(37) ((((37) & ~31) >> 1) +0xF0E0 0000 )

S3C2410_GPIO_BASE(37) =((10 0101 0 0000)>>1+0xF0E0 0000

= 1 0000+0xF0E0 0000

= 0xF0E1 0000

~31主要是为了清除S3C2410_GPB5的后5位,

2.

S3C2410_GPIO_OFFSET(pin);

S3C2410_GPIO_OFFSET作用是:根据端口编号pin,算出端口所在组的偏移量。((pin) & 31)即去掉比31大的数(清06位以上的位)。

5. __raw_readl__raw_writel

LinuxI/O的操作都定义在asm/io.h中,相应的在arm平台下,就在asm-arm/io.h中。

#define __raw_readl(a)   (__chk_io_ptr(a), *(volatile unsigned int __force   *)(a))
#define __raw_writel(v,a) (__chk_io_ptr(a), *(volatile unsigned int __force   *)(a) = (v))

include\linux\compiler.h中:

#ifdef __CHECKER__
……
extern void __chk_io_ptr(void __iomem *);
#else
……
# define __chk_io_ptr(x) (void)0
……
#endif

__raw_readl(a)展开是:((void)0, *(volatile unsigned int _force *)(a))。在定义了__CHECKER__的时候先调用__chk_io_ptr检查该地址,否则__chk_io_ptr什么也不做,*(volatile unsigned int _force *)(a)就是返回地址为a处的值。(void)xx的做法有时候是有用的,例如编译器打开了检查未使用的参数的时候需要将没有用到的参数这么弄一下才能编译通过。

CPUI/O的物理地址的编程方式有两种:一种是I/O映射,一种是内存映射。__raw_readl__raw_writel等是原始的操作I/O的方法,由此派生出来的操作方法有:inboutb_memcpy_fromioreadbwritebioread8iowrite8等。

6.local_irq_savelocal_irq_restore

关中断和开中断,在asm-arm/system.h中定义。

#define local_irq_save(x)      \

({        \

__asm__ __volatile__(      \

"mrs %0, cpsr   @ local_irq_save\n" \

"cpsid i"       \

: "=r" (x) : : "memory", "cc");     \

})

#define local_irq_save(x)      \

({        \

   unsigned long temp;     \

   (void) (&temp == &x);     \

__asm__ __volatile__(      \

"mrs %0, cpsr   @ local_irq_save\n" \

" orr %1, %0, #128\n"      \

" msr cpsr_c, %1"      \

: "=r" (x), "=r" (temp)      \

:        \

: "memory", "cc");      \

})

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