We have transplanted dm9000 today, as shown in the following figure. First of all, we should understand the Linux management driver architecture, which we have known before;
Add the following code in arch/ARM/plat-s3c24xx/common-smdk.c to register resources and add NICs to the device table:
/* Dm9000 */
# If defined (config_dm9000) | defined (config_dm9000_module)
Static struct resource initi_dm9k_resource [] = {
[0] = {
. Start = s3c2410_cs4,
. End = s3c2410_cs4 + 3,
. Flags = ioresource_mem,
},
[1] = {
. Start = s3c2410_cs4 + 4,
. End = s3c2410_cs4 + 4 + 3,
. Flags = ioresource_mem,
},
[2] = {
. Start = irq_eint7,
. End = irq_eint7,
. Flags = ioresource_irq,
}
};
/* For the moment we limit ourselves to 16bit Io until some
* Better Io routines can be written and tested
*/
Static struct dm9000_plat_data initi_dm9k_platdata = {
. Flags = dm9000_platf_16bitonly,
};
Static struct platform_device initi_device_dm9k = {
. Name = "dm9000 ",
. ID = 0,
. Num_resources = array_size (initi_dm9k_resource ),
. Resource = maid,
. Dev = {
. Platform_data = & cloud_dm9k_platdata,
}
};
# Endif
Add to kernel device list
Static struct platform_device _ initdata * smdk_devs [] = {
# If defined (config_dm9000) | defined (config_dm9000_module)
& Amp; cloud_device_dm9k,
# Endif
& Amp; cloud_device_nand,
& Smdk_led4,
& Smdk_led5,
& Smdk_led6,
& Smdk_led7,
};
Now we have to modify the corresponding code. Where can we modify the dm9000_probe? It completes the hardware enumeration, that is, the initialization. We need to modify it accordingly. Before the modification, we still need to know something; on the mini2440 Development Board, dm9000 is on bank4. Therefore, to make good use of dm9000, we need to set two registers related to the storage controller bank4, bwscon and bkcon4. For bwscon, we set four digits related to bank4. The settings are as follows:
# If defined (config_arch_s3c2410)
/*
* Wuxf: bank4 occupies 4*4 = 16 bits of bwscon. The value ranges from 16th bits to 16 bits. The data mask pin is 0 using wait signals */
Oldval_bwscon = * (volatile unsigned int *) s3c2410_bwscon );
* (Volatile unsigned int *) s3c2410_bwscon) = (oldval_bwscon &~ (3 <16 ))/
| S3c2410_bwscon_dw4_16 | s3c2410_bwscon_ws4 | s3c2410_bwscon_st4;
/*
* Wuxf: Please refer to the Data Manual of S3C2440.
*/
Oldval_bankcon4 = * (volatile unsigned int *) s3c2410_bankcon4 );
* (Volatile unsigned int *) s3c2410_bankcon4) = 0x345c;
# Endif
Bancon4: Read Data Manual
What is written above? Well, if we operate a sequencer, the time sequence is very important, and the write operation is the time sequence of the device. If we have set it, in the future, when operating the hardware S3C2440, the corresponding device sequence will be automatically provided, so that we can set it once, for convenience. So what do these time series mean? Let's take a look. For device timing, we need to analyze the device data manual. Let's find the Data Manual of dm9000 and first look at the time sequence:
T1: the time when the address signal is valid before the Iow is valid
T2: The validity period of the write Signal
T3: data time before the Iow signal disappears
T4: Data Retention Time
T5: The retention time of the address before the Iow signal disappears.
T6: The interval between the next write signal and the end of the signal
T7: Valid time of the address signal io16 and io32
T8: the time when the address signal is invalid, such as io16 and io32.
We have seen all the time periods clearly. Now we can see how our S3C2440 sorted the time. By the way, we only need to find the corresponding line, refer to the S3C2440 schematic. The connection between our S3C2440 and dm9000 is as follows:
Introduction layer of dm9000 (for good-looking purposes) S3C2440
Pw_rst-> nrest
SD0-SD15 à ldata0-ldata15-> DATA0-DATA15
CMD-> laddr2-> addr2
IRT-> I _lan-> eint7
Ior-> lnoe-> Noe
Iow-> lnwe-> Nwe
Iowait-> nwait
Aen-> nlan_cs-> gps4
So we need to know the time series provided by IOW, IOR, and so on, that is, the sequence of NOE, new, and so on. Let's continue to look at the time series of S3C2440 for bank4:
We can find out the correspondence between the time series segments of S3C2440 and dm9000:
Dm9000 S3C2440
T1 TCOs
T2 tacc
T3 TACs + TCOs + tacc
T4 tacp + toch + tcah
T5 tacp + toch
T6 tacp + toch + tcah + TACs + TCOs
When hclk is MHz (bank4 uses hclk), a clock cycle is 10ns, according to the minimum time of the T1-T6 (Note: We can lengthen the time, however, there must also be a moderate degree, because a long time may slow down the processing speed of the NIC. This can be done by setting two time series with different lengths to check the ping latency, in the same network) We assign the following values to TCOs:
T1 ---- TCOs 2 clocks 20ns> 5ns
T2 --- tacc 6 clock 60ns> 22ns note that when using wait signals, tacc must be greater than or equal to four clock
T3 --- TACs + TCOs + tacc Tacs one clock: 10 + 20 + 60 = 80ns> 22ns
T5 --- tacp + toch one clock, tacp six clock: 10 + 60 = 70ns> 5ns
T4 --- tacp + toch + tcah one clock: 60 + 10 + 10 = 80ns> 5ns
T6 --- tacp + toch + tcah + TACs + TCOs 60 + 10 + 10 + 10 + 20 = 110> 84ns
Comparison: TACs: 01, TCOs: 10, tacc: 100, tcoh: 01, tcah: 01, tacp: 11, PMC: 00 (one cycle can only process one data, so PMC should be normal (1 data), so the corresponding bancon4 is: 0x345c
The code is almost changed. Now we need to compile the code into the kernel. Therefore, we need to modify the Kernel configuration and compile the Code related to dm9000 into the kernel:
Make menuconfig à device drivers à Network Device Support (Ethernet (10 or 100 Mbit) à <*> dm9000 support.
# Make
......
Run and modify the corresponding IP address to check whether the IP address can be run. The result is Nic recognition, but ping different hosts. Where is the problem? Google...
It turns out that my Nic was interrupted but not initialized. As a result, the NIC could not be interrupted when receiving data, resulting in Ping failure. This should be the problem. Continue to check the NIC interruption. The ENI is disconnected from eint7, so we need to set it as follows:
1) set gpfcon (56000050) gpf7 [] to 10 and function to eint7.
This can be implemented using the function: s3c2410_gpio_cfgpin (s3c2410_gpf7, s3c2410_gpf3_eint7 );
2) extint0 (56000088) [30: 28] Set 0 Low Level Trigger interrupt (reset to all 0 by default, may not need to be set)
3) External Interrupt shielding register. Eintmask (56213a4) [7] Set 0 to enable interrupt eint7
4) intmask (4a000008) [4] sets 0 to enable eint4_7.
You can add the following in the function:
Static int
Dm9000_probe (struct platform_device * pdev ){
...
/* Added by wuxf inorder to support net */
Extint0 = ioremap_nocache (extint0, 4 );//
Intmsk = ioremap_nocache (intmsk, 4 );
Eintmsk = ioremap_nocache (eintmask, 4 );
S3c2410_gpio_cfgpin (s3c2410_gpf7, s3c2410_gpf7_eint7 );
Writel (readl (extint0) & 0x8fffffff, extint0); // eint7 low level
Writel (readl (intmsk )&(~ (1 <4), intmsk );//
Writel (readl (extint0 )&(~ (1 <7), extint0 );
Iounmap (intmsk );
Iounmap (extint0 );
Iounmap (eintmsk );
}
How to open it? You can trace the BSP function of S3C2440.
Start Compilation
# Make
...
Result: The ping operation is successful. The NIC is successfully transplanted.
This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/diantouxiao/archive/2010/04/02/5446130.aspx