micro2440采用S3C2440处理器,和这个平台相关的代码主要在arch/arm/mach-s3c2410和include/asm-arm/arch-s3c2410中,相关驱动在drivers目录中。
(1)DM9000 网卡驱动
Linux-2.6.32.2/drivers/net/dm9000.c
(2)串口(包括三个串口驱动0,1,2,对应设备名/dev/ttySAC0,1,2)
Linux-2.6.32.2/drivers/serial/s3c2440.c
(3)实时时钟RTC 驱动
Linux-2.6.32.2/drivers/rtc/rtc-s3c.c
(4)LED 驱动
Linux-2.6.32.2/drivers/char/mini2440_leds.c
(5)按键驱动
Linux-2.6.32.2/drivers/char/mini2440_buttons.c
(6)触摸屏驱动
Linux-2.6.32.2/drivers/input/touchscreen/s3c2410_ts.c
(7)yaffs2 文件系统源代码目录
Linux-2.6.32.2/fs/yaffs2
(8)USB 鼠标、键盘源代码
Linux-2.6.32.2/drivers/usb/hid
(9)SD/MMC 卡驱动源代码目录(支持高速最大容量32G SD 卡)
Linux-2.6.32.2/drivers/mmc
(10)Nand Flash 驱动
Linux-2.6.32.2/drivers/mtd/nand
(11)UDA1341 音频驱动目录
Linux-2.6.32.2/sound/soc/s3c24xx
(12)LCD 驱动
Linux-2.6.32.2/drivers/video/s3c2410fb.c
(13)优盘支持驱动
Linux-2.6.32.2/drivers/usb/storage
(14)万能USB 摄像头驱动
Linux-2.6.32.2/drivers/media/video/gspca
(15)I2C-EEPROM 驱动
inux-2.6.32.2/drivers/i2c
(16)背光驱动
Linux-2.6.32.2/drivers/video/mini2440_backlight.c
(17)PWM 控制蜂鸣器驱动
Linux-2.6.32.2/drivers/char/mini2440_pwm.c
(18)看门狗驱动
Linux-2.6.32.2/drivers/watchdog/s3c2410_wdt.c
(19)AD 转换驱动
Linux-2.6.32.2/drivers/char/mini2440_ad.c
(20)CMOS 摄像头驱动
Linux-2.6.32.2/drivers/media/video/s3c2440camif.c
(21)USB 无线网卡驱动(型号:TL-WN321G+)
Linux-2.6.32.2/drivers/net/wireless/rt2x00
(22)USB 转串口驱动
Linux-2.6.32.2/drivers/usb/serial/pl2302.c
#define S3C2410_GPIONO(bank,offset) ((bank) + (offset))
#define S3C2410_GPB5 S3C2410_GPIONO(S3C2410_GPIO_BANKB, 5)
上面的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的第10、11两位用于配置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 //写数据到端口,写0,或者写1
s3c2410_gpio_getpin //从端口读数据
这些函数的实现在gpio.h中
(自己的理解:dat = __raw_readl(base + 0x04); dat &= ~(1 << offs); dat |= to << offs;譬如操作的是端口5,这几句能保证其他的端口保持原值,而仅仅是端口5值改变)
4.S3C2410_GPIO_BASE和S3C2410_GPIO_OFFSET也是在regs-gpio.h文件中定义,
S3C2410_GPIO_OFFSET作用是:根据端口编号pin,算出端口所在组的偏移量。((pin) & 31)即去掉比31大的数(清0第6位以上的位)。
5. __raw_readl和__raw_writel
Linux对I/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的做法有时候是有用的,例如编译器打开了检查未使用的参数的时候需要将没有用到的参数这么弄一下才能编译通过。
CPU对I/O的物理地址的编程方式有两种:一种是I/O映射,一种是内存映射。__raw_readl和__raw_writel等是原始的操作I/O的方法,由此派生出来的操作方法有:inb、outb、_memcpy_fromio、readb、writeb、ioread8、iowrite8等。
6.local_irq_save和local_irq_restore
关中断和开中断,在asm-arm/system.h中定义。
(1)DM9000 网卡驱动
Linux-2.6.32.2/drivers/net/dm9000.c
(2)串口(包括三个串口驱动0,1,2,对应设备名/dev/ttySAC0,1,2)
Linux-2.6.32.2/drivers/serial/s3c2440.c
(3)实时时钟RTC 驱动
Linux-2.6.32.2/drivers/rtc/rtc-s3c.c
(4)LED 驱动
Linux-2.6.32.2/drivers/char/mini2440_leds.c
(5)按键驱动
Linux-2.6.32.2/drivers/char/mini2440_buttons.c
(6)触摸屏驱动
Linux-2.6.32.2/drivers/input/touchscreen/s3c2410_ts.c
(7)yaffs2 文件系统源代码目录
Linux-2.6.32.2/fs/yaffs2
(8)USB 鼠标、键盘源代码
Linux-2.6.32.2/drivers/usb/hid
(9)SD/MMC 卡驱动源代码目录(支持高速最大容量32G SD 卡)
Linux-2.6.32.2/drivers/mmc
(10)Nand Flash 驱动
Linux-2.6.32.2/drivers/mtd/nand
(11)UDA1341 音频驱动目录
Linux-2.6.32.2/sound/soc/s3c24xx
(12)LCD 驱动
Linux-2.6.32.2/drivers/video/s3c2410fb.c
(13)优盘支持驱动
Linux-2.6.32.2/drivers/usb/storage
(14)万能USB 摄像头驱动
Linux-2.6.32.2/drivers/media/video/gspca
(15)I2C-EEPROM 驱动
inux-2.6.32.2/drivers/i2c
(16)背光驱动
Linux-2.6.32.2/drivers/video/mini2440_backlight.c
(17)PWM 控制蜂鸣器驱动
Linux-2.6.32.2/drivers/char/mini2440_pwm.c
(18)看门狗驱动
Linux-2.6.32.2/drivers/watchdog/s3c2410_wdt.c
(19)AD 转换驱动
Linux-2.6.32.2/drivers/char/mini2440_ad.c
(20)CMOS 摄像头驱动
Linux-2.6.32.2/drivers/media/video/s3c2440camif.c
(21)USB 无线网卡驱动(型号:TL-WN321G+)
Linux-2.6.32.2/drivers/net/wireless/rt2x00
(22)USB 转串口驱动
Linux-2.6.32.2/drivers/usb/serial/pl2302.c
1.S3C2410_GPB5是端口编号,定义在regs-gpio.h中,
搜索所在位置:
[root@localhost linux-2.6.32.2_fa]# find ./ -name "regs-gpio.h"
./arch/arm/mach-s3c2410/include/mach/regs-gpio.h
#define S3C2410_GPIONO(bank,offset) ((bank) + (offset))
#define S3C2410_GPB5 S3C2410_GPIONO(S3C2410_GPIO_BANKB, 5)
上面的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的第10、11两位用于配置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 //写数据到端口,写0,或者写1
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);
}
(自己的理解:dat = __raw_readl(base + 0x04); dat &= ~(1 << offs); dat |= to << offs;譬如操作的是端口5,这几句能保证其他的端口保持原值,而仅仅是端口5值改变)
4.S3C2410_GPIO_BASE和S3C2410_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的零头(清0低5位),>>1的原因是每组GPIO中最多可以有32个端口,控制这些端口需要4个寄存器空间,4个寄存器空间就需要4*4=16个字节进行编址,32/16=2,左移一位刚好满足。也就是说,上一组端口和下一组端口的编号相差32,而控制寄存器的地址相差16。(自己的理解:因为每个GPIO口对应4个寄存器,每个寄存器32位,S3C2410_GPIO_BASE仅仅是算出虚拟基址,而不管是哪个具体端口,2的5次方正好是32,((pin) & ~31)可以屏蔽掉低五位,右移一位是因为端口数不超过32,每个GPIO口对应4个寄存器,每个寄存器32位,4*32/8=16=0x10,例如GPIOA=0X10+S3C24XX_VA_GPIO ,GPIOB=0X20+S3C24XX_VA_GPIO,0x10所表示的数的个数超过32)S3C2410_GPIO_OFFSET作用是:根据端口编号pin,算出端口所在组的偏移量。((pin) & 31)即去掉比31大的数(清0第6位以上的位)。
5. __raw_readl和__raw_writel
Linux对I/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的做法有时候是有用的,例如编译器打开了检查未使用的参数的时候需要将没有用到的参数这么弄一下才能编译通过。
CPU对I/O的物理地址的编程方式有两种:一种是I/O映射,一种是内存映射。__raw_readl和__raw_writel等是原始的操作I/O的方法,由此派生出来的操作方法有:inb、outb、_memcpy_fromio、readb、writeb、ioread8、iowrite8等。
6.local_irq_save和local_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"); \
})