ARMSYS2440开发板原来的内核版本为linux2.6.12,这次要求移植高版本内核,并打上rt补丁,使之变成实时内核。
移植步骤主要参考 http://blog.csdn.net/yang_dk/archive/2008/04/17/2300712.aspx
移植环境:
主机:ubuntu 9.04
交叉编译器:arm-linux-gcc-3.4.1
开发板平台:S3C2440(ARMSYS2440开发板)
准备工作:
1. 下载源码:http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.31.12.tar.bz2
2. 安装交叉编译工具:自带的工具包,工具安装在/usr/local/arm/3.4.1/中。
3. 解压源码:tar jxvf linux-2.6.31.12.tar.bz2
开始移植:
1. 修改配置文件
1). 修改内核根目录下Makefile,设定ARM的编译环境.
在193行找到ARCH
修改为
ARCH = arm
CROSS_COMPILE = /usr/local/arm/3.4.1/bin/arm-linux-
CORSS_COMPILE视自己的环境定
2). 添加devfs支持
为了内核支持devfs 以及在启动时并在/sbin/init 运行之前能自动挂载/dev为devfs 文件系统。编辑fs/Kconfig:
在906 行menu "Pseudo filesystems"下面添加如下代码:
config DEVFS_FS
bool "/dev file system support (OBSOLETE)"
default y
config DEVFS_MOUNT
bool "Automatically mount at boot"
default y
depends on DEVFS_FS
2. 修改源代码
1). 修改对nand的分区信息,与bootloader一致,可以从以前板子上内核源码的arch/arm/mach-s3c2410/devs.c中找到。
在arch/arm/plat-s3c24xx/common-smdk.c中修改smdk_default_nand_part[],注意这个一定要跟bootloader的一致。修改如下:
static struct mtd_partition smdk_default_nand_part[] = {
[0] = {
.name = "Boot",
.size = 0x00030000,
.offset = 0
},
[1] = {
.name = "Kernel",
.size = 0x001d0000,
.offset = 0x00030000,
},
[2] = {
.name = "RootFileSystem",
/*.size = 0x01e00000, //30M*/
.size = 0x03300000,
.offset = 0x00200000,
},
[3] = {
.name = "ExtendFileSystem",
.size = 0x00b00000,
.offset = 0x03500000,
}
};
另外此文件还要修改smdk_nand_info如下:
static struct s3c2410_platform_nand smdk_nand_info = {
.tacls = 0, // 20
.twrph0 = 30,// 60
.twrph1 = 0, // 20
.nr_sets = ARRAY_SIZE(smdk_nand_sets),
.sets = smdk_nand_sets,
};
2). 修改时钟
在arch/arm/mach-s3c2440/mach-smdk2440.c中修改smdk2440_map_io如下
static void __init smdk2440_map_io(void)
{
s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
s3c24xx_init_clocks(12000000); //default is 16934400
s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
}
另,我们板子上的uboot没有2440的MACH_TYPE匹配号,因此它用的还是2410的mach号,内核源码中2410的时钟启动为s3c24xx_init_clocks(0);默认启动(arch/arm/mach-s3c2410/mach-smdk2410.c)。故修改arch/arm/mach-s3c2410/mach-smdk2410.c中的0为16934400:
static void __init smdk2410_map_io(void)
{
s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
s3c24xx_init_clocks(16934400); // 0
s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
}
3). 修改nand Flash的校验方式,去掉ECC校验。
在drivers/mtd/nand/s3c2410.c 第841行
将chip->ecc.mode = NAND_ECC_SOFT;
改为 chip->ecc.mode = NAND_ECC_NONE;
3. 配置编译内核
可以将开发板内核源码中原来的.config文件拷过来直接使用。
若要自行配置,可把把默认配置文件拷贝过来
cp arch/arm/configs/s3c2410_defconfig .config
配置:make menuconfig
确认以下选项都有:
[*] Enable loadable module support --->
[*] Module unloading
System Type ---->
[*] S3C2410 DMA support
S3C2410 Machines --->
[*] SMDK2410/A9M2410
S3C2440 Machines --->
[*] SMDK2440
[*] SMDK2440 with S3C2440 CPU module
Boot option ----->
修改启动参数为:
root=/dev/mtdblock2 init=/linuxrc console=ttySAC0,115200 display=L35T32 rootfstype=cramfs devfs=mount
Device Drivers --->
<*> Memory Technology Device (MTD) support --->
[*] MTD partitioning support
<*> NAND Device Support --->
<*> NAND Flash support for S3C2410/S3C2440 SoC
[ ] S3C2410 NAND Hardware ECC //这个要去掉
[*] Network device support --->
[*] Ethernet (10 or 100Mbit) --->
<*> CS89x0 support
< > Real Time Clock ---> //这个去掉
File systems --->
<*> ROM file system support
因为我的文件系统用cramfs,选择这个,其他用默认。
4. 编译内核
make zImage
编译成功,烧写到板子上。
启动后,网卡驱动有误,因此需修改CS89x0驱动代码。
5. 移植CS89X0网卡驱动
1). 修改arch/arm/plat-s3c24xx/include/plat/common-smdk.h,添加宏定义:
#define __IRQT_FALEDGE IRQ_TYPE_EDGE_FALLING
#define __IRQT_RISEDGE IRQ_TYPE_EDGE_RISING
#define __IRQT_LOWLVL IRQ_TYPE_LEVEL_LOW
#define __IRQT_HIGHLVL IRQ_TYPE_LEVEL_HIGH
#define IRQT_NOEDGE (0)
#define IRQT_RISING (__IRQT_RISEDGE)
#define IRQT_FALLING (__IRQT_FALEDGE)
#define IRQT_BOTHEDGE (__IRQT_RISEDGE|__IRQT_FALEDGE)
#define IRQT_LOW (__IRQT_LOWLVL)
#define IRQT_HIGH (__IRQT_HIGHLVL)
#define IRQT_PROBE IRQ_TYPE_PROBE
#define pSMDK2410_ETH_IO __phys_to_pfn(0x19000000)
#define vSMDK2410_ETH_IO 0xE0000000
#define SMDK2410_ETH_IRQ IRQ_EINT9
2). 修改arch/arm/mach-s3c2410/mach-smdk2410.c,添加网卡物理映射:
static struct map_desc smdk2410_iodesc[] __initdata = {
/* nothing here yet */
{vSMDK2410_ETH_IO,pSMDK2410_ETH_IO,SZ_1M,MT_DEVICE} // 8900
};
3). 修改cs89x0.c,以下是diff文件,diff -ruN file1 file2:
@@ -174,6 +174,27 @@
static unsigned int netcard_portlist[] __used __initdata =
{ 0x0300, 0};
static unsigned int cs8900_irq_map[] = {1,0,0,0};
+
+#elif defined(CONFIG_ARCH_S3C2410) //Added zhangw
+#include <linux/irq.h>
+#include <asm/irq.h>
+#include <mach/irqs.h>
+#include <mach/regs-mem.h>
+#include <mach/regs-gpio.h>
+#include <plat/common-smdk.h>
+static unsigned int netcard_portlist[] __initdata = { vSMDK2410_ETH_IO +
+DEFAULTIOBASE, 0};
+static unsigned int cs8900_irq_map[] = {SMDK2410_ETH_IRQ , 0, 0, 0};
+
+#ifdef request_region
+#undef request_region
+#endif
+#ifdef release_region
+#undef release_region
+#endif
+#define request_region(a,s,n) request_mem_region(a,s,n)
+#define release_region(a,s) release_mem_region(a,s)
+
#elif defined(CONFIG_MACH_IXDP2351)
static unsigned int netcard_portlist[] __used __initdata = {IXDP2351_VIRT_CS8900_BASE, 0};
static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0};
@@ -324,6 +345,13 @@
netdev_boot_setup_check(dev);
io = dev->base_addr;
irq = dev->irq;
+
+#ifdef CONFIG_ARCH_S3C2410 // add by zhangw
+ __raw_writel((__raw_readl(S3C2410_GPGCON)&~(0x3<<2))|(0x2<<2),S3C2410_GPGCON);
+ __raw_writel((__raw_readl(S3C2410_EXTINT1)&~(0x7<<4))|(0x4<<4),S3C2410_EXTINT1);
+ __raw_writel(0x2211d110,S3C2410_BWSCON);
+ __raw_writel(0x1f7c,S3C2410_BANKCON3);
+#endif
if (net_debug)
printk("cs89x0:cs89x0_probe(0x%x)/n", io);
@@ -387,6 +415,19 @@
{
outw(value, base_addr + (portno << 1));
}
+#elif defined(CONFIG_ARCH_S3C2410) // add by zhangw
+static u16
+readword(unsigned long base_addr, int portno)
+{
+ return __raw_readw(base_addr+portno);
+}
+
+static void
+writeword(unsigned long base_addr, int portno,u16 value)
+{
+ __raw_writew(value,base_addr+portno);
+}
+
#else
static u16
readword(unsigned long base_addr, int portno)
@@ -653,7 +694,20 @@
the driver will always do *something* instead of complain that
adapter_cnf is 0. */
-#ifdef CONFIG_SH_HICOSH4
+#if defined CONFIG_ARCH_S3C2410 // add by zhangw
+ lp->force=FORCE_RJ45;
+ lp->auto_neg_cnf=IMM_BIT;
+
+ dev->dev_addr[0]=0x00; /*setMACaddress*/
+ dev->dev_addr[1]=0x00;
+ dev->dev_addr[2]=0x02;
+ dev->dev_addr[3]=0x50;
+ dev->dev_addr[4]=0x10;
+ dev->dev_addr[5]=0x08;
+
+#elif defined CONFIG_SH_HICOSH4
+
+//#ifdef CONFIG_SH_HICOSH4
if (1) {
/* For the HiCO.SH4 board, things are different: we don't
have EEPROM, but there is some data in flash, so we go
@@ -1280,7 +1334,7 @@
int i;
int ret;
-#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX010X) /* uses irq#1, so this won't work */
+#if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX010X)&& !defined(CONFIG_ARCH_S3C2410) /* uses irq#1, so this won't work */ // add by zhangw
if (dev->irq < 2) {
/* Allow interrupts to be generated by the chip */
/* Cirrus' release had this: */
@@ -1311,7 +1365,7 @@
else
#endif
{
-#ifndef CONFIG_CS89x0_NONISA_IRQ
+#if !defined(CONFIG_CS89x0_NONISA_IRQ)&& !defined(CONFIG_ARCH_S3C2410)// add by zhangw
if (((1 << dev->irq) & lp->irq_map) == 0) {
printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x/n",
dev->name, dev->irq, lp->irq_map);
@@ -1326,6 +1380,10 @@
writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);
#endif
write_irq(dev, lp->chip_type, dev->irq);
+#if defined(CONFIG_ARCH_S3C2410) // add by zhangw
+ set_irq_type(dev->irq, IRQT_RISING);
+
+#endif
ret = request_irq(dev->irq, &net_interrupt, 0, dev->name, dev);
if (ret) {
if (net_debug)
@@ -1396,7 +1454,7 @@
case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break;
default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2);
}
-#ifdef CONFIG_ARCH_PNX010X
+#if defined(CONFIG_ARCH_PNX010X) || defined(CONFIG_ARCH_S3C2410) // add by zhangw
result = A_CNF_10B_T;
#endif
if (!result) {
4). make menuconfig进入内核配置,在网络驱动中将 CS89x0 support 选中。
重新编译内核并烧写,启动成功。
6. 打rt补丁
1). 下载rt补丁:
2). patch补丁:
bzip2 -dc patch-2.6.31.12-rt21.bz2 | patch -p1
3). 检查内核配置,主要参考 http://rt.wiki.kernel.org/index.php/RT_PREEMPT_HOWTO
4). 增加rtc设备,修改arch/arm/mach-s3c2410/mach-smdk2410.c:
static struct platform_device *smdk2410_devices[] __initdata =
{
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c0,
&s3c_device_iis,
&s3c_device_rtc,
};
5). 编译内核,出现编译错误:
include/asm-generic/cmpxchg-local.h中的wrong_size_cmpxchg的定义体找不到。屏蔽之。
编译通过,烧之,正常启动成功。