Chinaunix首页 | 论坛 | 博客
  • 博客访问: 345665
  • 博文数量: 208
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 286
  • 用 户 组: 普通用户
  • 注册时间: 2014-05-20 11:39
文章分类

全部博文(208)

文章存档

2014年(208)

我的朋友

分类: LINUX

2014-05-20 13:00:40

原文地址:cs8900a网卡驱动移植 作者:mutes


cs8900内部有两种访问内部寄存器的方式:
1. I/O模式: 就是非统一编址的情况中使用in/out等特殊指令访问的方式。接到独立的io总线上面。
2. memory模式: 统一编址,和访问内存一样,接到地址总线上。
                                                   
由两根线决定使用I/O模式还是memory模式,AEN 和 A[24]
___     _____
AEN  +  A[24]    ---> I/O 模式
AEN  +  A[24]    ---> memory 模式

cs8900接在2号blank中,所以基地址为0x18000000,但是由因为s3c2440是统一编址的,所以我们需要选用memory模式,所以第24位一定要1,所以我们访问cs8900的时候基地址为0x19000000.

cs8900访问寄存器的方法比较特别,0x19000000其实还不是寄存器的基地址,手册告诉我们"I/O Base Address"是0x300,所以基地址是0x19000300. 而只cs8900只有3个地址可以访问:
0x19000300 + 0x00    Tx/Rx data 这个地址用来发送和接收数据用的。
如果要访问其他的寄存器,就要用下面的方法:
1. 0x19000300 + 0x0a 把我们要访问的寄存器的偏移写到这个地址中,告诉cs8900我们要访问那个寄存器
2. 0x19000300 + 0x0c 现在我们可以通过访问这个地址来操作那个寄存器。

注意,cs8900的所有数据和寄存器都是16位的。

中断:
            +--------+                 +---------+
电频中断    |        |  边沿触发       |         |
     .------| CS8900 |--.  .--.  .--.  | arm920t |
-----'      |        |  '--'  '--'  '--|         |
物理网口    +--------+  EINT9 外部中断 +---------+

test_setup:
1. ioremap 0x19000000 --> virt
2. base_addr = virt + 0x300

test_open:
1. 用base_addr + 0x0a 写寄存器的地址
   用base_addr + 0x0c 操作这个地址就可以操作对应的寄存器,包括读和写
2. request_irq

test_tx:
1. 配置相应的寄存器
2. 将要发送的数据连续写入base_addr+0x00

test_rx:
1. 读取相应寄存器的状态
2. 从base_addr+0x00连续读入收到的地址

cs8900关于内存的初始化有两个寄存器:
1. BWSCON 设置2号blank的位宽,cs8900用16位宽,设置enable
WAIT,因为cs8900采用20M的时钟,不能像内存那么快,所以我们要wait.还有要设置UB/LB,这一位是什么意思呢?就是说如果上面我们选用了16bit的位宽,但是又想以字节为单位访问内存,如果不设置这一位的话,用ldrb指令也不能按照bytes来取数据,这个能不能按照bytes来取数据最后还是要看接在总线上的设备支不支持,所以不是所有接在总线上面的设备都可以按照byte来访问。
2. BANKCON1 设置cs8900在内存控制器这边的时序,cs8900的时序在手册中找到。
3.由于每个板子的地址不一样,那些引脚的初始化,还有读写的执行。没有提到。



一.   根据原理图,确认网卡的地址和中断号
地址:0x19000000
中断号: EINT9



二.   修改drivers/net/ethernet/cirrus/cs89x0.c,指定CS8900A使用的资源
 186 #elif defined(CONFIG_ARCH_S3C2410)
 187 #include
 188 #define S3C24XX_PA_CS8900   0x19000000
 189 static unsigned int netcard_portlist[] __initdate = {0, 0};
 190 static unsigned int cs8900_irq_map[] = {IRQ_EINT9, 0, 0, 0};

三.   修改入口函数cs89x0_probe
1.      
#if defined(CONFIG_ARCH_S3C2410)
       unsigned int oldval_bwscon;
       unsigned int oldval_bankcon3;
#endif

2.  设置MAC,总线宽度等:

#if defined(CONFIG_ARCH_S3C2410)
if(netcard_portlist[0])
return -ENODEV;
netcard_portlist[0] = (unsigned int)ioremap(S3C24XX_PA_CS8900, SZ_1M) + 0x300;

dev->dev_addr[0] = 0x08;
dev->dev_addr[1] = 0x89;
dev->dev_addr[2] = 0x89;
dev->dev_addr[3] = 0x89;
dev->dev_addr[4] = 0x89;
dev->dev_addr[5] = 0x89;

oldval_bwscon = *((volatile unsigned int *)S3C2410_BWSCON);
*((volatile unsigned int *)S3C2410_BWSCON) = (oldval_bwscon & ~(3<<12)) | S3C2410_BWSCON_DW3_16 | S3C2410_BWSCON_WS3 | S3C2410_BWSCON_ST3;
oldval_bankcon3 = *((volatile unsigned int *)S3C2410_BANKCON3);
*((volatile unsigned int *)S3C2410_BANKCON3) = 0x1f7c;
#endif

3.   出错退出

out:
#if defined(CONFIG_ARCH_S3C2410)
       iounmap(netcard_portlist[0]);
       netcard_portlist[0] = 0;
       *((volatile unsigned int *)S3C2410_BWSCON) = oldval_bwscon;
        *((volatile unsigned int *)S3C2410_BANKCON3) = oldval_bankcon3;
#endif

       free_netdev(dev);

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