由于linux已经对mini2440提供了支持,这里只做少许的修改。
(1)驱动能用模块方式就用模块方式,尽可能少地向内核添加文件
(2)修改最少的代码,且在修改时使用条件编译
(3)尽可能不修改内核源代码
(1)为内核打上yaffs2补丁
./patch-ker.sh c m ../linux-2.6.38.7
(2)配置内核
make mini2440_defconfig ARCH=arm
make ARCH=arm menuconfig
(3)修改arch/arm/mach-s3c2440/mach-mini2440.c
修改LCD参数:
如果使用默认的LCD参数,在我的LCD上(T35)向右偏移了很多,这里做如下修改
static struct s3c2410fb_display mini2440_lcd_cfg[] __initdata = {
[0] = { /* mini2440 + 3.5" TFT + touchscreen */
_LCD_DECLARE(
7, /* The 3.5 is quite fast */
240, 21, 38, 6, /* x timing */
320, 4, 4, 2, /* y timing */
240, 1, 26, 5, /* x timing */
320, 2, 5, 2, /* y timing */
……
修改backlight
static char mini2440_features_str[12] __initdata = "0tb";
static char mini2440_features_str[12] __initdata = "0t";
即不使用backlight,因为如果使用backlight的话,LCD会熄灭背光,直到加载友善之臂提供的backlight驱动。
修改IIC:删除IIC相关内容
如果采用内核默认的IIC,友善提供的EEPROM读写程序将不能执行,只有去除IIC相关内容或将24c08的地址改为0xA0后才能使用,具体原因尚不清楚,需要阅读内核源代码。
static void __init mini2440_init(void)
{
……
i2c_register_board_info(0, mini2440_i2c_devs,
ARRAY_SIZE(mini2440_i2c_devs));
……
}
或者是
static struct i2c_board_info mini2440_i2c_devs[] __initdata = {
{
I2C_BOARD_INFO("24c08", 0x50),
I2C_BOARD_INFO("24c08", 0xA0),
.platform_data = &at24c08,
},
};
关于LED和Button
Linux的LED驱动和button还是比好的,比如读写nand或mmc时LED就会亮,而button则使用了输入子系统,如将KEY1设置为KEY_RIGHT,则按KEY1时Qt的选择的图标就会向右移动。
我的选择是将LED1设为nand-disk触发,LED2设为mmc0触发,LED3和LED4留出来做其他使用。
KEY1~KEY6设置为KEY_UP、KEY_DOWN、KEY_LEFT、KEY_RIGHT、KEY_SPACE、KEY_ESC,虽然内核默认注释掉了K6,但是开启K6后没有出现问题。
内核提供了input子系统的button程序,但如果将button编译进内核,内核会将button创建为input0,这样Qt默认使用button而不能再使用友善提供的触摸屏驱动,因此,这里button也采用模块方式,并在加载模块时先加载触摸屏,再加载gpio-keys.ko
(4)驱动移植
UDA134x
sound/soc/codecs/uda134x.c
static int uda134x_startup(struct snd_pcm_substream *substream,......)
{
......
uda134x->slave_substream = substream;
} else
uda134x->master_substream = substream;
#if defined( CONFIG_MACH_MINI2440 )
uda134x_write(codec, 2, 2 |(5U<<2)); /* 把录音通道改为 VIN2 */
#endif
return 0;
}
DM9000
dm9000可以不修改,但是ping时丢包率很高,一般在70%,建议修改,修改后丢包率在20%以下。
drivers/net/dm9000.c
static int __init
dm9000_init(void)
{
#if defined(CONFIG_MACH_MINI2440)
#include <mach/regs-mem.h>
unsigned int oldval_bwscon = *(volatile unsigned int *)S3C2410_BWSCON;
*((volatile unsigned int *)S3C2410_BWSCON) = (oldval_bwscon & ~(3<<16)) |
S3C2410_BWSCON_DW4_16 | S3C2410_BWSCON_WS4 |
S3C2410_BWSCON_ST4;
*((volatile unsigned int *)S3C2410_BANKCON4) = 0x1f7c;
#endif
printk(KERN_INFO "%s Ethernet Driver, V%s/n", CARDNAME, DRV_VERSION);
return platform_driver_register(&dm9000_driver);
}
其他驱动,如adc、backlight、pwm、touchscreen、LED、button采用模块的方式。LED驱动要修改一下,因为已经使用了LED1和LED2,这里可用的就只有LED3和LED4了。还需要指出的是友善自带的ADC和PWM驱动在linux-2.6.38.7中不能通过编译,本人在网上搜到一个解决方法,但是要修改内核代码,这并不是我所需要的,看来还是搞懂代码后自己再写一个的好。
(5)编译内核
make ARCH=arm CROSS_COMPILE=arm-linux- zImage
可以使用-jn指定编译的进程数,n一般设为处理器个数的3倍,如果使用单核,则用-j2。
(6)编译模块
make ARCH=arm CROSS_COMPILE=arm-linux- modules
配置选项根据实际情况裁剪,比如我不使用无线网络和USB转串口的驱动等,但注意以下两点:
Kernel Features --->
[*] Provide old way to pass kernel parameters
不选的话supervivi和uboot不能将参数传递给内核
Device Drivers --->
Input device support --->
[*] Keyboards --->
<M> GPIO Buttons
这里将按键编译为模块方式,原因见上。如果不使用内核提供的button驱动,这个就不用选了。