一、S3C2410和CS8900的硬件连接
FS2410开发板的原理图我没有找到,但可看参考资料2,里面写的非常详细
二、移植过程
a) 配置内核支持S3C2410
选好Samsung S3C24XX SoCs后,会自动返回到上一级菜单(即前一张图),然后选择:
b) 配置内核支持CS89x0网卡
Device Drivers-->Network device support-->Ethernet driver support—>
c) 修改drivers/net/ethenet/cirrus/cs89x0.c:
(1)在文件开头增加以下几行,它们在宏CONFIG_ARCH_S3C24XX被定义时起作用,表示作用于FS2410开发板
183 static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
184 #elif defined(CONFIG_ARCH_S3C24XX)
185 #include
186 #include
187 #define S3C24XX_PA_CS8900 0x19000000 /* 物理基地址 */
188 static unsigned int netcard_portlist[] __initdata = {0, 0}; /* 在下面进行设置 */
189 static unsigned int cs8900_irq_map[] = {IRQ_EINT9, 0, 0, 0}; /* 中断号*/
190 #else
191 #ifndef CONFIG_CS89x0_PLATFORM
192 static unsigned int netcard_portlist[] __used __initdata =
(2)修改入口函数cs89x0_probe
以下使用宏CONFIG_ARCH_S3C24XX包裹起来的代码是新加的
311 struct net_device * __init cs89x0_probe(int unit)
312 {
313 struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
314 unsigned *port;
315 int err = 0;
316 int irq;
317 int io;
318 #if defined(CONFIG_ARCH_S3C24XX)
319 unsigned int oldval_bwscon; /* 用来保存BWSCON寄存器的值 */
320 unsigned int oldval_bankcon3; /* 用来保存S3C2410_BANKCON3寄存器的值 */
321 #endif
322 if (!dev)
323 return ERR_PTR(-ENODEV);
324
325 sprintf(dev->name, "eth%d", unit);
326 netdev_boot_setup_check(dev);
327 io = dev->base_addr;
328 irq = dev->irq;
329 #if defined(CONFIG_ARCH_S3C24XX)
330 // cs89x0_probe会被调用多次,我们只需要1次,根据netcard_portlist[0]的值忽略后面的调用
331 if (netcard_portlist[0])
332 return -ENODEV;
333 // 将CS8900A的物理地址转换为虚拟地址,0x300是CS8900A内部的IO空间的偏移地址
334 netcard_portlist[0] = (unsigned int)ioremap(S3C24XX_PA_CS8900, SZ_1M) + 0x300;
335 /* 设置默认MAC地址,
336 * MAC地址可以由CS8900A外接的EEPROM设定(有些单板没接EEPROM),
337 * 或者启动系统后使用ifconfig修改
338 */
339 dev->dev_addr[0] = 0x08;
340 dev->dev_addr[1] = 0x89;
341 dev->dev_addr[2] = 0x89;
342 dev->dev_addr[3] = 0x89;
343 dev->dev_addr[4] = 0x89;
344 dev->dev_addr[5] = 0x89;
345 /* 设置Bank3: 总线宽度为16, 使能nWAIT, 使能UB/LB。by www.100ask.net */
346 oldval_bwscon = *((volatile unsigned int *)S3C2410_BWSCON);
347 *((volatile unsigned int *)S3C2410_BWSCON) = (oldval_bwscon & ~(3<<12))
348 | S3C2410_BWSCON_DW3_16 | S3C2410_BWSCON_WS3 | S3C2410_BWSCON_ST3;
349 /* 设置BANK3的时间参数, by www.100ask.net */
350 oldval_bankcon3 = *((volatile unsigned int *)S3C2410_BANKCON3);
351 *((volatile unsigned int *)S3C2410_BANKCON3) = 0x1f7c;
352 #endif
353 if (net_debug)
354 printk("cs89x0:cs89x0_probe(0x%x)n", io);
355
356 if (io > 0x1ff) { /* Check a single specified location. */
357 err = cs89x0_probe1(dev, io, 0);
358 } else if (io != 0) { /* Don't probe at all. */
359 err = -ENXIO;
360 } else {
361 for (port = netcard_portlist; *port; port++) {
362 if (cs89x0_probe1(dev, *port, 0) == 0)
363 break;
364 dev->irq = irq;
365 }
366 if (!*port)
367 err = -ENODEV;
368 }
369 if (err)
370 goto out;
371 return dev;
372 out:
373 #if defined(CONFIG_ARCH_S3C24XX)
374 iounmap(netcard_portlist[0]);
375 netcard_portlist[0] = 0;
376
377 /* 恢复寄存器原来的值 */
378 *((volatile unsigned int *)S3C2410_BWSCON) = oldval_bwscon;
379 *((volatile unsigned int *)S3C2410_BANKCON3) = oldval_bankcon3;
380 #endif
381 free_netdev(dev);
382 printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected. Be sure to disable PnP with SETUPn");
383 return ERR_PTR(err);
384 }
385 //#endif 多了一个
386 #endif
(3)修改模块入口函数init_module
以下使用宏CONFIG_ARCH_S3C24XX包裹起来的代码是新加的
1879 int __init init_module(void)
1880 {
1881 struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
1882 struct net_local *lp;
1883 int ret = 0;
1884 #if defined(CONFIG_ARCH_S3C24XX)
1885 unsigned int oldval_bwscon; /* 用来保存BWSCON寄存器的值 */
1886 unsigned int oldval_bankcon3; /* 用来保存S3C2410_BANKCON3寄存器的值 */
1887 #endif
1888 #if DEBUGGING
1889 net_debug = debug;
1890 #else
1891 debug = 0;
1892 #endif
1893 if (!dev)
1894 return -ENOMEM;
1895
1896 #if defined(CONFIG_ARCH_S3C24XX)
1897 // 将CS8900A的物理地址转换为虚拟地址,0x300是CS8900A内部的IO空间的偏移地址
1898 dev->base_addr = io = (unsigned int)ioremap(S3C24XX_PA_CS8900, SZ_1M) + 0x300;
1899 dev->irq = irq = cs8900_irq_map[0]; /* 中断号 */
1900
1901 /* 设置默认MAC地址,
1902 * MAC地址可以由CS8900A外接的EEPROM设定(有些单板没接EEPROM),
1903 * 或者启动系统后使用ifconfig修改
1904 */
1905 dev->dev_addr[0] = 0x08;
1906 dev->dev_addr[1] = 0x89;
1907 dev->dev_addr[2] = 0x89;
1908 dev->dev_addr[3] = 0x89;
1909 dev->dev_addr[4] = 0x89;
1910 dev->dev_addr[5] = 0x89;
1911
1912 /* 设置Bank3: 总线宽度为16, 使能nWAIT, 使能UB/LB。by www.100ask.net */
1913 oldval_bwscon = *((volatile unsigned int *)S3C2410_BWSCON);
1914 *((volatile unsigned int *)S3C2410_BWSCON) = (oldval_bwscon & ~(3<<12))
1915 | S3C2410_BWSCON_DW3_16 | S3C2410_BWSCON_WS3 | S3C2410_BWSCON_ST3;
1916
1917 /* 设置BANK3的时间参数, by www.100ask.net */
1918 oldval_bankcon3 = *((volatile unsigned int *)S3C2410_BANKCON3);
1919 *((volatile unsigned int *)S3C2410_BANKCON3) = 0x1f7c;
1920 #else
1921 dev->irq = irq;
1922 dev->base_addr = io;
1923 #endif
… …
1971 out:
1972 #if defined(CONFIG_ARCH_S3C24XX)
1973 iounmap(dev->base_addr);
1974
1975 /* 恢复寄存器原来的值 */
1976 *((volatile unsigned int *)S3C2410_BWSCON) = oldval_bwscon;
1977 *((volatile unsigned int *)S3C2410_BANKCON3) = oldval_bankcon3;
1978 #endif
1979 free_netdev(dev);
1980 return ret;
1981 }
(4)修改模块退出函数cleanup_module
以下使用宏CONFIG_ARCH_S3C24XX包裹起来的代码是新加的
1983 void __exit
1984 cleanup_module(void)
1985 {
1986 unregister_netdev(dev_cs89x0);
1987 writeword(dev_cs89x0->base_addr, ADD_PORT, PP_ChipID);
1988 release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT);
1989 #if defined(CONFIG_ARCH_S3C24XX)
1990 iounmap(dev_cs89x0->base_addr);
1991 #endif
1992 free_netdev(dev_cs89x0);
1993 }
1994 #endif /* MODULE && !CONFIG_CS89x0_PLATFORM */
1995
(5)修改net_open
1240 net_open(struct net_device *dev)
1241 {
1242 struct net_local *lp = netdev_priv(dev);
1243 int result = 0;
1244 int i;
1245 int ret;
1246 #if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX010X) && !defined(CONFIG_ARCH_S3C24XX) /* uses irq#1, so this won't work */
1247 if (dev->irq < 2) {
1248 /* Allow interrupts to be generated by the chip */
1249 /* Cirrus' release had this: */
1250 #if 0
1251 writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );
1252 #endif
1253 /* And 2.3.47 had this: */
1254 writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);
... ...
1273 }
1274 else
1275 #endif
1276 {
1277 #if !defined(CS89x0_NONISA_IRQ) && !defined(CONFIG_CS89x0_PLATFORM)&& !defined(CONFIG_ARCH_S3C24XX)
1278 if (((1 << dev->irq) & lp->irq_map) == 0) {
1279 printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %xn",
1280 dev->name, dev->irq, lp->irq_map);
1281 ret = -EAGAIN;
1282 goto bad_out;
1283 }
1284 #endif
1285 /* FIXME: Cirrus' release had this: */
1286 writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );
1287 /* And 2.3.47 had this: */
1288 #if 0
1289 writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON);
1290 #endif
1291 write_irq(dev, lp->chip_type, dev->irq);
1292 #if defined(CONFIG_ARCH_S3C24XX)
1293 ret = request_irq(dev->irq, &net_interrupt, IRQF_TRIGGER_RISING, dev->name, dev);
1294 #else
1295 ret = request_irq(dev->irq, net_interrupt, 0, dev->name, dev);
1296 #endif
1297 if (ret) {
1298 printk(KERN_ERR "cs89x0: request_irq(%d) failedn", dev->irq);
1299 goto bad_out;
1300 }
1301 }
... ...
1358 /* check to make sure that they have the "right" hardware available */
1359 switch(lp->adapter_cnf & A_CNF_MEDIA_TYPE) {
1360 case A_CNF_MEDIA_10B_T: result = lp->adapter_cnf & A_CNF_10B_T; break;
1361 case A_CNF_MEDIA_AUI: result = lp->adapter_cnf & A_CNF_AUI; break;
1362 case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break;
1363 default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2);
1364 }
1365 #if defined(CONFIG_ARCH_PNX010X) || defined(CONFIG_ARCH_S3C24XX)
1366 result = A_CNF_10B_T;
1367 #endif
1368 if (!result) {
1369 printk(KERN_ERR "%s: EEPROM is configured for unavailable median", dev->name);
1370 release_dma:
... ...
1478 }
(6)全局变量static int io 修改为static unsigned int io;
原因请看参考资料1
最后,编译内核,执行make uImage。
三、参考资料
1、《嵌入式linux应用开发完全手册》韦东山
2、《FS2410中CS8900A IO模式驱动分析》杨志平
3、S3C2410 内存连接方法的深入研究
4、(转)CS8900A 驱动程序分析(国嵌)
5、AUI与BNC - BaiShi 在路上 - CSDN博客