移植Linux2.6.22.2到友善之臂SBC2440V4(s3c2440AL)(双网卡)
这次移植除了使用我以前的移植纪录外,还重点参考了:
(0)S3C2440英文数据手册
(1)《linux内核中设置CPU工作频率》URL:
(2)DM9000英文数据手册
首先,Linux2.6.22.2本身就支持s3c2440处理器,由于2410和2440基本兼容,所以在linux源码里2440的很多文件是和2410共用的。所以在按照我移植2410记录的基础上,主要修改如下:
一、开发板选项的选择。
System Type --->
S3C2440 Machines --->
[*] SMDK2440
[*] SMDK2440 with S3C2440 CPU module
留下这两项就够了,S3C2400 Machines ---> 、S3C2410 Machines --->、S3C2412 Machines --->、S3C2442 Machines --->、S3C2443 Machines --->里的项目全部“N”掉。
这两个选项是区分你的目标芯片是2410还是2440的关键选项!!
二、系统初始化时的芯片晶振频率的修改,修改arch/arm/mach-s3c2440/mach-smdk2440.c
......
static void __init smdk2440_map_io(void)
{
s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
s3c24xx_init_clocks(12000000);
s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
}
......
如果没有改这个参数,系统启动时到了"done, booting the kernel."之后就会出现乱码现象或是没有输出。我一开始就碰到了这个麻烦。出现此类乱码或没有输出现象的另一个原因可能是你的bootloader对CPU的主频和分频的设置不正确。SBC2440V4的设置最好是时钟频率405MHz,分频比为1:4:8,不然有可能出现上述现象。请看参考资料(1)。
三、开发板四个LED指示灯的驱动修改
SBC2440V4和SMDK2440一样有四个LED指示灯。指示用的GPIO口不一样。参考SBC2440V4的硬件说明书,修改/arch/arm/plat-s3c24xx/common-smdk.c如下:
......
static struct s3c24xx_led_platdata smdk_pdata_led4 = {
.gpio = S3C2410_GPB5,
.flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
.name = "led4",
.def_trigger = "timer",
};
static struct s3c24xx_led_platdata smdk_pdata_led5 = {
.gpio = S3C2410_GPB6,
.flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
.name = "led5",
.def_trigger = "nand-disk",
};
static struct s3c24xx_led_platdata smdk_pdata_led6 = {
.gpio = S3C2410_GPB7,
.flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
.name = "dm9000",
};
static struct s3c24xx_led_platdata smdk_pdata_led7 = {
.gpio = S3C2410_GPB8,
.flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
.name = "cs89x0",
};
......
void __init smdk_machine_init(void)
{
/* Configure the LEDs (even if we have no LED support)*/
s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPB5_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPB6, S3C2410_GPB6_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPB7, S3C2410_GPB7_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPB8, S3C2410_GPB8_OUTP);
s3c2410_gpio_setpin(S3C2410_GPB5, 1);
s3c2410_gpio_setpin(S3C2410_GPB6, 1);
s3c2410_gpio_setpin(S3C2410_GPB7, 0);
s3c2410_gpio_setpin(S3C2410_GPB8, 0);
if (machine_is_smdk2443())
smdk_nand_info.twrph0 = 50;
s3c_device_nand.dev.platform_data = &smdk_nand_info;
platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));
s3c2410_pm_init();
}
......
修改成功的现象,启动时LED1和LED2会亮一下;nand flash 读写时LED2会闪动;dm9000有网络活动时,LED3会亮;cs8900有网络活动时,LED4会亮。由于dm9000是作为NFS挂载的网卡,所以LED3亮的时间比较多。
四、修改/driver/net/Kconfig文件,使其在配置时出现cs89x0的选项。
......
config CS89x0
tristate "CS89x0 support"
---help---
depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X)
Support for CS89x0 chipset based Ethernet cards. If you have a
network (Ethernet) card of this type, say Y and read the
Ethernet-HOWTO, available from
<> as well as
.
To compile this driver as a module, choose M here and read
. The module will be
called cs89x0.
就是使 depends on NET_PCI && (ISA || MACH_IXDP2351 || ARCH_IXDP2X01 || ARCH_PNX010X)那一句失效。我是把它放到了 ---help---下面,你也可以把它删了。
以下是双网卡的移植,首先要说明的是如果都编译进内核中,双网卡在启动时会无法挂载NFS,会出现IP配置失败的提示。单独编译时都不会出现这种情况。原因我不知道。(那位大侠如果解决了记得通知一声) 经过多次试验发现:要实现双网卡,又要挂载NFS根文件系统最好的配置是将DM9000编译进内核(速度快),将
CS8900作为模块在启动后挂载。以下的移植就是针对这种情况修改的。
五、修改/driver/net/cs89x0.c文件,使其匹配SBC2440V4和cs8900的硬件配置。(并添加LED4在有网络操作时点亮的功能)
......
#include
#include
#include
#include
#if ALLOW_DMA
#include
#endif
#include "cs89x0.h"
//**********************tekkaman*************************
#include
#include
#include
#include
#include
#include
#define CS8900_BASE (S3C2440_VA_ISA_CS8900)
#define CS8900_IRQ IRQ_EINT9
//**********************tekkaman*****************************
static char version[] __initdata =
"cs89x0.c: v2.4.3-pre1 Russell Nelson <>, Andrew Morton <";
DEFINE_LED_TRIGGER(cs89x0_led_trigger);
#define DRV_NAME "cs89x0"
......
#define CIRRUS_DEFAULT_IRQ VH_INTC_INT_NUM_CASCADED_INTERRUPT_1 /* Event inputs bank 1 - ID 35/bit 3 */
static unsigned int netcard_portlist[] __initdata = {CIRRUS_DEFAULT_BASE, 0};
static unsigned int cs8900_irq_map[] = {CIRRUS_DEFAULT_IRQ, 0, 0, 0};
#else
static unsigned int netcard_portlist[] __initdata = {CS8900_BASE, 0};
static unsigned int cs8900_irq_map[] = {CS8900_IRQ,0};
#endif
/* Index to functions, as function prototypes. */
static int cs89x0_probe1(struct net_device *dev,unsigned int ioaddr, int modular);
......
//static int get_eeprom_cksum(int off, int len, int *buffer);
......
struct net_device * __init cs89x0_probe(int unit)
{
struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
unsigned int *port;
int err = 0;
unsigned int irq;
unsigned int io;
//tekkaman
static int once=0;
unsigned int value;
//tekkaman
if (!dev)
return ERR_PTR(-ENODEV);
sprintf(dev->name, "eth%d", unit);
netdev_boot_setup_check(dev);
//******************************tekkaman********************************
if (once) {
return -ENXIO;
}
value = __raw_readl(S3C2410_BWSCON);
value &= ~(S3C2410_BWSCON_WS3|S3C2410_BWSCON_ST3|S3C2410_BWSCON_DW3_32);
value |= (S3C2410_BWSCON_WS3|S3C2410_BWSCON_ST3|S3C2410_BWSCON_DW3_16);
__raw_writel(value, S3C2410_BWSCON);
value=0;
value = (S3C2410_BANKCON_Tacs0|S3C2410_BANKCON_Tcos4|S3C2410_BANKCON_Tacc14|S3C2410_BANKCON_Tcoh1|S3C2410_BANKCON_Tcah4|S3C2410_BANKCON_Tacp6|S3C2410_BANKCON_PMCnorm);
__raw_writel(value,S3C2410_BANKCON3);
set_irq_type(CS8900_IRQ,IRQ_TYPE_EDGE_RISING );
s3c2410_gpio_cfgpin(S3C2410_GPG1, S3C2410_GPG1_EINT9);
s3c2410_gpio_pullup(S3C2410_GPG1, 0);
if(dev->base_addr==0){
dev->base_addr = CS8900_BASE ;
dev->irq = CS8900_IRQ;
once++;
}
led_trigger_register_simple("cs89x0", &cs89x0_led_trigger);
//***********************************tekkaman************************************
io = dev->base_addr;
irq = dev->irq;
......
}
......
#else
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);
}
#endif
......
#if 0
static int __init
get_eeprom_cksum(int off, int len, int *buffer)
{
int i, cksum;
cksum = 0;
for (i = 0; i < len; i++)
cksum += buffer[i];
cksum &= 0xffff;
if (cksum == 0)
return 0;
return -1;
}
#endif
......
static int __init
cs89x0_probe1(struct net_device *dev, unsigned int ioaddr, int modular)
{
struct net_local *lp = netdev_priv(dev);
static unsigned version_printed;
int i;
int tmp;
unsigned rev_type = 0;
// int eeprom_buff[CHKSUM_LEN];
int retval;
unsigned char ne_defethaddr[]={0x08,0x08,0x08,0x08,0x27,0x12,0};//tekkaman
SET_MODULE_OWNER(dev);
/* Initialize the device structure. */
if (!modular) {
memset(lp, 0, sizeof(*lp));
spin_lock_init(&lp->lock);
#ifndef MODULE
#if ALLOW_DMA
if (g_cs89x0_dma) {
lp->use_dma = 1;
lp->dma = g_cs89x0_dma;
lp->dmasize = 16; /* Could make this an option... */
}
#endif
// lp->force = g_cs89x0_media__force;
lp->force = (FORCE_RJ45 | FORCE_FULL);
lp->auto_neg_cnf=IMM_BIT;
......
#if 0
if ((readreg(dev, PP_SelfST) & (EEPROM_OK | EEPROM_PRESENT)) ==
(EEPROM_OK|EEPROM_PRESENT)) {
/* Load the MAC. */
for (i=0; i < ETH_ALEN/2; i++) {
unsigned int Addr;
Addr = readreg(dev, PP_IA+i*2);
dev->dev_addr[i*2] = Addr & 0xFF;
dev->dev_addr[i*2+1] = Addr >> 8;
}
......
if (net_debug > 1)
printk(KERN_DEBUG "%s: new adapter_cnf: 0x%x\n",
dev->name, lp->adapter_cnf);
}
#endif
for (i = 0; i < ETH_ALEN; i++) {
dev->dev_addr[i] = ne_defethaddr[i];
}
/* allow them to force multiple transceivers. If they force multiple, autosense */
{
int count = 0;
if (lp->force & FORCE_RJ45) {lp->adapter_cnf |= A_CNF_10B_T; count++; }
if (lp->force & FORCE_AUI) {lp->adapter_cnf |= A_CNF_AUI; count++; }
if (lp->force & FORCE_BNC) {lp->adapter_cnf |= A_CNF_10B_2; count++; }
if (count > 1) {lp->adapter_cnf |= A_CNF_MEDIA_AUTO; }
else if (lp->force & FORCE_RJ45){lp->adapter_cnf |= A_CNF_MEDIA_10B_T; }
else if (lp->force & FORCE_AUI) {lp->adapter_cnf |= A_CNF_MEDIA_AUI; }
else if (lp->force & FORCE_BNC) {lp->adapter_cnf |= A_CNF_MEDIA_10B_2; }
}
......
static int
detect_tp(struct net_device *dev)
{
......
if ((readreg(dev, PP_LineST) & LINK_OK) == 0)
return DETECTED_NONE;
lp->force = (FORCE_RJ45 | FORCE_FULL);
lp->auto_neg_cnf=IMM_BIT;
if (lp->chip_type == CS8900) {
switch (lp->force & 0xf0) {
......
}
......
static int
net_open(struct net_device *dev)
{
......
if (i >= CS8920_NO_INTS) {
writereg(dev, PP_BusCTL, 0); /* disable interrupts. */
printk(KERN_ERR "cs89x0: can't get an interrupt\n");
ret = -EAGAIN;
goto bad_out;
}
}
else
#endif
{
#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X) && !defined(CONFIG_ARCH_S3C2410)
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);
ret = -EAGAIN;
goto bad_out;
}
#endif
......
/* set the Ethernet address */
for (i=0; i < ETH_ALEN/2; i++)
writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
/* while we're testing the interface, leave interrupts disabled */
writereg(dev, PP_BusCTL, MEMORY_ON);
/* Set the LineCTL quintuplet based on adapter configuration read from EEPROM */
if ((lp->adapter_cnf & A_CNF_EXTND_10B_2) && (lp->adapter_cnf & A_CNF_LOW_RX_SQUELCH))
lp->linectl = LOW_RX_SQUELCH;
else
lp->linectl = 0;
lp->adapter_cnf |= A_CNF_10B_T | A_CNF_MEDIA_10B_T ;
/* check to make sure that they have the "right" hardware available */
switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
case A_CNF_MEDIA_10B_T: result = lp->adapter_cnf & A_CNF_10B_T; break;
case A_CNF_MEDIA_AUI: result = lp->adapter_cnf & A_CNF_AUI; break;
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);
}
......
}
......
static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
{
struct net_local *lp = netdev_priv(dev);
led_trigger_event(cs89x0_led_trigger, LED_FULL);
......
led_trigger_event(cs89x0_led_trigger, LED_OFF);
return 0;
}
/* The typical workload of the driver:
Handle the network interface interrupts. */
static irqreturn_t net_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct net_local *lp;
unsigned int ioaddr, status;
int handled = 0;
......
}
......
static void
net_rx(struct net_device *dev)
{
struct net_local *lp = netdev_priv(dev);
struct sk_buff *skb;
int status, length;
led_trigger_event(cs89x0_led_trigger, LED_FULL);
unsigned int ioaddr = dev->base_addr;
status = readword(ioaddr, RX_FRAME_PORT);
length = readword(ioaddr, RX_FRAME_PORT);
......
led_trigger_event(cs89x0_led_trigger, LED_OFF);
}
......
#ifdef MODULE
static struct net_device *dev_cs89x0;
/*
* Support the 'debug' module parm even if we're compiled for non-debug to
* avoid breaking someone's startup scripts
*/
static unsigned int io=CS8900_BASE;
static unsigned int irq=CS8900_IRQ;
static int debug;
static char media[8]="rj45";
static int duplex=-1;
static int use_dma; /* These generate unused var warnings if ALLOW_DMA = 0 */
static int dma;
static int dmasize=16; /* or 64 */
module_param(io, uint, 0);
module_param(irq, uint, 0);
module_param(debug, int, 0);
......
int __init init_module(void)
{
struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
struct net_local *lp;
int ret = 0;
#if DEBUGGING
net_debug = debug;
#else
debug = 0;
#endif
//tekkaman
unsigned int value;
value = __raw_readl(S3C2410_BWSCON);
value &= ~(S3C2410_BWSCON_WS3|S3C2410_BWSCON_ST3|S3C2410_BWSCON_DW3_32);
value |= (S3C2410_BWSCON_WS3|S3C2410_BWSCON_ST3|S3C2410_BWSCON_DW3_16);
__raw_writel(value, S3C2410_BWSCON);
value=0;
value = (S3C2410_BANKCON_Tacs0|S3C2410_BANKCON_Tcos4|S3C2410_BANKCON_Tacc14|S3C2410_BANKCON_Tcoh1|S3C2410_BANKCON_Tcah4|S3C2410_BANKCON_Tacp6|S3C2410_BANKCON_PMCnorm);
__raw_writel(value,S3C2410_BANKCON3);
set_irq_type(CS8900_IRQ,IRQ_TYPE_EDGE_RISING );
s3c2410_gpio_cfgpin(S3C2410_GPG1, S3C2410_GPG1_EINT9);
s3c2410_gpio_pullup(S3C2410_GPG1, 0);
led_trigger_register_simple("cs89x0", &cs89x0_led_trigger);
//tekkaman
if (!dev)
return -ENOMEM;
......
}
......
特别说明:除了总线配置语句一定要加,否则网卡运行时会出现“time out”的错误之外,还有一个十分重要的地方:在驱动中存储 基地址 和中断 的变量一点要统一定义为unsigned int 否则会出错。
六、修改/driver/net/dm9000.c文件,使其匹配SBC2440V4和DM9000的硬件配置(并添加LED3在有网络操作时点亮的功能)
......
#include //LED驱动头文件
......
//**********************tekkaman*************************
#include
#include
#include
#include
#include
#include
#define DM9000_IRQ IRQ_EINT7
//**********************tekkaman*****************************
/*
* Transmit timeout, default 5 seconds.
*/
static int watchdog = 5000;
module_param(watchdog, int, 0400);
MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
DEFINE_LED_TRIGGER(dm9000_led_trigger);
......
static void dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg,
int value);
//static u16 read_srom_word(board_info_t *, int);
static void dm9000_rx(struct net_device *);
static void dm9000_hash_table(struct net_device *);
//tekkaman
#undef DM9000_PROGRAM_EEPROM
//tekkaman
#ifdef DM9000_PROGRAM_EEPROM
static void program_eeprom(board_info_t * db);
#endif
......
#if 0
//def CONFIG_NET_POLL_CONTROLLER
/*
*Used by netconsole
*/
static void dm9000_poll_controller(struct net_device *dev)
{
disable_irq(dev->irq);
dm9000_interrupt(dev->irq,dev);
enable_irq(dev->irq);
}
#endif
......
static int
dm9000_probe(struct platform_device *pdev)
{
struct dm9000_plat_data *pdata = pdev->dev.platform_data;
struct board_info *db; /* Point a board information structure */
struct net_device *ndev;
unsigned char ne_defethaddr[]={0x08,0x08,0x08,0x08,0x12,0x27,0};//tekkaman
unsigned long base;
int ret = 0;
int iosize;
int i;
u32 id_val;
//******************************tekkaman********************************
unsigned int value;
static int once=0;
if (once) {
return -ENXIO;
}
//tekkaman
value = __raw_readl(S3C2410_BWSCON);
value &= ~(S3C2410_BWSCON_WS4|S3C2410_BWSCON_ST4|S3C2410_BWSCON_DW4_32);
value |= (S3C2410_BWSCON_ST4|S3C2410_BWSCON_DW4_16);
__raw_writel(value, S3C2410_BWSCON);
value=0;
value = (S3C2410_BANKCON_Tacs4|S3C2410_BANKCON_Tcos4|S3C2410_BANKCON_Tacc14|S3C2410_BANKCON_Tcoh4|S3C2410_BANKCON_Tcah4|S3C2410_BANKCON_Tacp6|S3C2410_BANKCON_PMCnorm);
__raw_writel(value,S3C2410_BANKCON4);
set_irq_type(DM9000_IRQ,IRQ_TYPE_LEVEL_HIGH );
s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_EINT7);
s3c2410_gpio_pullup(S3C2410_GPF7, 0);
//******************************tekkaman********************************
/* Init network device */
ndev = alloc_etherdev(sizeof (struct board_info));
if (!ndev) {
printk("%s: could not allocate device.\n", CARDNAME);
return -ENOMEM;
}
......
#if 0
def CONFIG_NET_POLL_CONTROLLER
ndev->poll_controller = &dm9000_poll_controller;
#endif
#ifdef DM9000_PROGRAM_EEPROM
program_eeprom(db);
#endif
db->msg_enable = NETIF_MSG_LINK;
db->mii.phy_id_mask = 0x1f;
db->mii.reg_num_mask = 0x1f;
db->mii.force_media = 0;
db->mii.full_duplex = 0;
db->mii.dev = ndev;
db->mii.mdio_read = dm9000_phy_read;
db->mii.mdio_write = dm9000_phy_write;
/* Read SROM content */
//tekkaman
/* for (i = 0; i < 64; i++)
((u16 *) db->srom)[i] = read_srom_word(db, i);
*/
/* Set Node Address */
for (i = 0; i < 6; i++)
ndev->dev_addr[i] = ior(db, i+DM9000_PAR);
//tekkaman
if (!is_valid_ether_addr(ndev->dev_addr)) {
/* try reading from mac */
printk("%s: Invalid ethernet MAC address."
" Load ne_defethaddr !! \n ", ndev->name);
for (i = 0; i < 6; i++)
ndev->dev_addr[i] = ne_defethaddr[i];
}
if (!is_valid_ether_addr(ndev->dev_addr))
printk("%s: Invalid ethernet MAC address. Please "
"set using ifconfig\n", ndev->name);
......
/*
* Initilize dm9000 board
*/
static void
dm9000_init_dm9000(struct net_device *dev)
{
board_info_t *db = (board_info_t *) dev->priv;
PRINTK1("entering %s\n",__FUNCTION__);
......
/* Init Driver variable */
db->tx_pkt_cnt = 0;
db->queue_pkt_len = 0;
dev->trans_start = 0;
spin_lock_init(&db->lock);
}
static int
dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
board_info_t *db = (board_info_t *) dev->priv;
PRINTK3("dm9000_start_xmit\n");
led_trigger_event(dm9000_led_trigger, LED_FULL);
if (db->tx_pkt_cnt > 1)
return 1;
......
led_trigger_event(dm9000_led_trigger, LED_OFF);
return 0;
}
......
static void
dm9000_rx(struct net_device *dev)
{
board_info_t *db = (board_info_t *) dev->priv;
struct dm9000_rxhdr rxhdr;
struct sk_buff *skb;
u8 rxbyte, *rdptr;
bool GoodPacket;
int RxLen;
/* Check packet ready or not */
do {
led_trigger_event(dm9000_led_trigger, LED_FULL);
ior(db, DM9000_MRCMDX); /* Dummy read */
......
led_trigger_event(dm9000_led_trigger, LED_OFF);
} while (rxbyte == DM9000_PKT_RDY);
}
/*
* Read a word data from SROM
*/
#if 0
static u16
read_srom_word(board_info_t * db, int offset)
{
iow(db, DM9000_EPAR, offset);
iow(db, DM9000_EPCR, EPCR_ERPRR);
mdelay(8); /* according to the datasheet 200us should be enough,
but it doesn't work */
iow(db, DM9000_EPCR, 0x0);
return (ior(db, DM9000_EPDRL) + (ior(db, DM9000_EPDRH) << 8));
}
#endif
......
static int __init
dm9000_init(void)
{
printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME);
led_trigger_register_simple("dm9000", &dm9000_led_trigger);
return platform_driver_register(&dm9000_driver); /* search board and register */
}
......
特别说明:static int dm9000_probe(struct platform_device *pdev)函数中的总线配置语句一定要加,否则网卡运行时会出现“time out”的错误。
七、修改文件/arch/arm/mach-s3c2440/mach-smdk2440.c,增加对DM9000和CS8900的配置信息。
......
#include
#define DM9000_BASE (vDM9000_BASE)
#define DM9000_IRQ IRQ_EINT7
#define pDM9000_BASE S3C2440_PA_ISA_DM9000
#define vDM9000_BASE S3C2440_VA_ISA_DM9000
#define CS8900_BASE (vCS8900_BASE)
#define CS8900_IRQ IRQ_EINT9
#define pCS8900_BASE S3C2440_PA_ISA_CS8900
#define vCS8900_BASE S3C2440_VA_ISA_CS8900
static struct map_desc smdk2440_iodesc[] __initdata = {
/* ISA IO Space map (memory space selected by A24) */
{
.virtual = (u32)S3C24XX_VA_ISA_WORD,
.pfn = __phys_to_pfn(S3C2410_CS1),
.length = 0x10000,
.type = MT_DEVICE,
}, {
.virtual = (u32)S3C24XX_VA_ISA_WORD + 0x10000,
.pfn = __phys_to_pfn(S3C2410_CS1 + (1<<24)),
.length = SZ_4M,
.type = MT_DEVICE,
}, {
.virtual = (u32)S3C24XX_VA_ISA_BYTE,
.pfn = __phys_to_pfn(S3C2410_CS1),
.length = 0x10000,
.type = MT_DEVICE,
}, {
.virtual = (u32)S3C24XX_VA_ISA_BYTE + 0x10000,
.pfn = __phys_to_pfn(S3C2410_CS1 + (1<<24)),
.length = SZ_4M,
.type = MT_DEVICE,
}, {
.virtual = S3C2440_VA_ISA_DM9000,
.pfn = S3C2440_PA_ISA_DM9000,
.length = S3C2440_SZ_ISA_DM9000,
.type = MT_DEVICE,
}, {
.virtual = S3C2440_VA_ISA_CS8900,
.pfn = S3C2440_PA_ISA_CS8900,
.length = S3C2440_SZ_ISA_CS8900,
.type = MT_DEVICE,
}
};
......
struct dm9000_plat_data tekkaman2440_dm9000 = {
.flags= DM9000_PLATF_16BITONLY
};
static struct resource s3c2440_dm9000_resource[] = {
[0] = {
.start = DM9000_BASE,
.end = DM9000_BASE + 0xff,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = DM9000_IRQ,
.end = DM9000_IRQ,
.flags = IORESOURCE_IRQ,
}
};
struct platform_device s3c_device_dm9000 = {
.name = "dm9000",
.id = -1,
.num_resources = ARRAY_SIZE(s3c2440_dm9000_resource),
.resource = s3c2440_dm9000_resource,
.dev = {
.platform_data = &tekkaman2440_dm9000,
}
};
static struct platform_device *smdk2440_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
&s3c_device_dm9000
};
......
八、修改文件/include/asm-arm/arch-s3c2410/map.h,增加DM9000和CS8900的配置信息。
......
/* ISA style IO, for each machine to sort out mappings for, if it
* implements it. We reserve two 16M regions for ISA.
*/
#define S3C24XX_VA_ISA_WORD S3C2410_ADDR(0x02000000)
#define S3C24XX_VA_ISA_BYTE S3C2410_ADDR(0x03000000)
/***************tekkaman****************************/
#define S3C2440_VA_ISA_DM9000 S3C2410_ADDR(0x02100300)
#define S3C2440_PA_ISA_DM9000 __phys_to_pfn(0x20000300)
#define S3C2440_SZ_ISA_DM9000 SZ_1M
#define S3C2440_VA_ISA_CS8900 S3C2410_ADDR(0x02200300)
#define S3C2440_PA_ISA_CS8900 __phys_to_pfn(0x19000300)
#define S3C2440_SZ_ISA_CS8900 SZ_1M
/**********************tekkaman********************/
......
特别说明:至于CS8900的物理地址的配置#define S3C2440_PA_ISA_CS8900 __phys_to_pfn(0x19000300),不一定非得0x19000300,也可以是0x1B000300、0x1D000300、0x1F000300,这是由于SBC2440V4的CS8900连接基本和SDMK2410的是一样的,使用了ADDR24脚作为类似使能的管脚。这样的设计是为了系统扩展的方便。
九、配置内核。
Networking --->
Networking options --->
[*] IP: kernel level autoconfiguration
[ ] IP: DHCP support
[ ] IP: BOOTP support
[ ] IP: RARP support
如果你的cs8900是编译进内核,这三项最好要去掉。如果你和我一样是编译成模块,“Y”、“M”和“N”都无所谓。
Device Drivers --->
Network device support --->
Ethernet (10 or 100Mbit) --->
[*] Ethernet (10 or 100Mbit)
--- Generic Media Independent Interface device support
< > SMC 91C9x/91C1xxx support
<*> DM9000 support
CS89x0 support
如果双网卡都编译进内核中,在启动时会无法挂载NFS,会出现IP配置失败的提示。单独编译时都不会出现这种情况。
最后就是make zImage 和make modules。将/drivers/net/cs89x0.ko复制到根文件系统中,启动后挂载。以下是我系统的一些信息:
[Tekkaman2440@SBC2410]#cd /lib/modules/
[Tekkaman2440@SBC2410]#insmod cs89x0.ko
eth%d: cs8900 rev K found at 0xf2200300 <6>cs89x0 media RJ-45, IRQ 53, programmed I/O, MAC 08:08:08:08:27:12
[Tekkaman2440@SBC2410]#ifconfig eth1 192.168.0.22
eth1: using full-duplex 10Base-T (RJ-45)
[Tekkaman2440@SBC2410]#ping 192.168.0.1
PING 192.168.0.1 (192.168.0.1): 56 data bytes
64 bytes from 192.168.0.1: seq=0 ttl=64 time=4.977 ms
64 bytes from 192.168.0.1: seq=1 ttl=64 time=0.633 ms
64 bytes from 192.168.0.1: seq=2 ttl=64 time=0.617 ms
64 bytes from 192.168.0.1: seq=3 ttl=64 time=0.601 ms
64 bytes from 192.168.0.1: seq=4 ttl=64 time=0.640 ms
64 bytes from 192.168.0.1: seq=5 ttl=64 time=0.621 ms
64 bytes from 192.168.0.1: seq=6 ttl=64 time=0.723 ms
64 bytes from 192.168.0.1: seq=7 ttl=64 time=0.623 ms
--- 192.168.0.1 ping statistics ---
8 packets transmitted, 8 packets received, 0% packet loss
round-trip min/avg/max = 0.601/1.179/4.977 ms
[Tekkaman2440@SBC2410]#ifconfig
eth0 Link encap:Ethernet HWaddr 08:08:08:08:12:27
inet addr:192.168.1.2 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:3485 errors:0 dropped:0 overruns:0 frame:0
TX packets:2382 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2704784 (2.5 MiB) TX bytes:422360 (412.4 KiB)
Interrupt:51 Base address:0x300
eth1 Link encap:Ethernet HWaddr 08:08:08:08:27:12
inet addr:192.168.0.22 Bcast:192.168.0.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:36 errors:0 dropped:0 overruns:0 frame:0
TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:4513 (4.4 KiB) TX bytes:826 (826.0 B)
Interrupt:53 Base address:0x300
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
整个移植工作到这里就结束了,我没时间复查,如果按上面的配置会出错。请通知一声,我会及时更正。