cs8900a網卡驅動移植


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 <mach/regs-mem.h>
 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);


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章