首先先上电路原理图,关于AT91芯片网卡部分的引脚:
内核源码中对网卡以及其他外设设备的驱动程序,设备的注册都在 Board_sam9260ek_.c文件中。
结构体原型:
/* Ethernet (EMAC & MACB) */
struct at91_eth_data {
u32phy_mask;
u8 phy_irq_pin;/* PHY IRQ */
u8 is_rmii;/* using RMII interface? */
};
注册为中断引脚为AT91_PIN_PA7,MII模式
/* MACB Ethernet device*/
static struct at91_eth_data __initdata ek_macb_data = {
.phy_irq_pin = AT91_PIN_PA7,
.is_rmii = 1,
};
添加设备
/* Ethernet */
at91_add_device_eth(&ek_macb_data);
static struct platform_device at91sam9260_eth_device = {
.name = "macb",
.id = -1,
.dev = {
.dma_mask = ð_dmamask,
.coherent_dma_mask= DMA_BIT_MASK(32),
.platform_data= ð_data,
},
.resource = eth_resources,
.num_resources= ARRAY_SIZE(eth_resources),
};
void __init at91_add_device_eth(struct at91_eth_data *data)
{
if (!data)
return;
if (data->phy_irq_pin) {
at91_set_gpio_input(data->phy_irq_pin, 0);
at91_set_deglitch(data->phy_irq_pin, 1);
}
/* Pins used for MII and RMII */
at91_set_A_periph(AT91_PIN_PA19, 0);/* ETXCK_EREFCK */
at91_set_A_periph(AT91_PIN_PA17, 0);/* ERXDV */
at91_set_A_periph(AT91_PIN_PA14, 0);/* ERX0 */
at91_set_A_periph(AT91_PIN_PA15, 0);/* ERX1 */
at91_set_A_periph(AT91_PIN_PA18, 0);/* ERXER */
at91_set_A_periph(AT91_PIN_PA16, 0);/* ETXEN */
at91_set_A_periph(AT91_PIN_PA12, 0);/* ETX0 */
at91_set_A_periph(AT91_PIN_PA13, 0);/* ETX1 */
at91_set_A_periph(AT91_PIN_PA21, 0);/* EMDIO */
at91_set_A_periph(AT91_PIN_PA20, 0);/* EMDC */
if (!data->is_rmii) {
at91_set_B_periph(AT91_PIN_PA28, 0);/* ECRS */
at91_set_B_periph(AT91_PIN_PA29, 0);/* ECOL */
at91_set_B_periph(AT91_PIN_PA25, 0);/* ERX2 */
at91_set_B_periph(AT91_PIN_PA26, 0);/* ERX3 */
at91_set_B_periph(AT91_PIN_PA27, 0);/* ERXCK */
at91_set_B_periph(AT91_PIN_PA23, 0);/* ETX2 */
at91_set_B_periph(AT91_PIN_PA24, 0);/* ETX3 */
at91_set_B_periph(AT91_PIN_PA22, 0);/* ETXER */
}
eth_data = *data;
platform_device_register(&at91sam9260_eth_device);
}
可以发现注册的为platform总线上的设备
在内核启动后可在 sys/bus/platform/devices中找到macb、除此之外,你也可以发现注册在platform总线上的nandflash、uart、spi、i2c等设备
[@SD9260: /]# cd sys/
[@SD9260: /sys]# ls
block class devices fs module
bus dev firmware kernel power
[@SD9260: /sys]# clear
[@SD9260: /sys]# ls
block class devices fs module
bus dev firmware kernel power
[@SD9260: /sys]# cd bus/
[@SD9260: bus]# ls
i2c mmc scsi serio usb
mdio_bus platform sdio spi
[@SD9260: bus]# cd platform/
[@SD9260: platform]# ls
devices drivers_autoprobe uevent
drivers drivers_probe
[@SD9260: platform]# cd devices/
[@SD9260: devices]# ls
at91_mci atmel_nand atmel_usart.1 atmel_usart.5 macb
at91_ohci atmel_spi.0 atmel_usart.2 atmel_usart.6 ssc.0
at91_rtt.0 atmel_spi.1 atmel_usart.3 i2c-gpio
at91_udc atmel_usart.0 atmel_usart.4 leds-gpio
[@SD9260: devices]# cd macb/
[@SD9260: macb]# ls
bus driver modalias net:eth0 power subsystem uevent
Bit | Bit Name | Default | Description |
15 | Reset | 0, RW/SC | Reset: 1 = Initiate software Reset / Reset in Process. 0 = Normal operation. This bit, which is self-clearing, returns a value of one until the reset process is complete. The configuration is re-strapped. |
14 | Loopback | 0, RW | Loopback: 1 = Loopback enabled. 0 = Normal operation. The loopback function enables MII transmit data to be routed to the MII receive data path. Setting this bit may cause the descrambler to lose synchronization and produce a 500 µs “dead time” before any valid data will appear at the MII receive outputs. |
13 | Speed Selection | RW | Speed Select: When auto-negotiation is disabled writing to this bit allows the port speed to be selected. 1 = 100 Mb/s. 0 = 10 Mb/s. |
12 | Auto-Negotiation Enable | RW | Auto-Negotiation Enable: Strap controls initial value at reset. 1 = Auto-Negotiation Enabled - bits 8 and 13 of this register are ignored when this bit is set. 0 = Auto-Negotiation Disabled - bits 8 and 13 determine the port speed and duplex mode. |
11 | Power Down | 0, RW | Power Down: 1 = Power down. 0 = Normal operation. Setting this bit powers down the PHY. Only the register block is enabled during a power-down condition. |
10 | Isolate | 0, RW | Isolate: 1 = Isolates the Port from the MII with the exception of the serial management. 0 = Normal operation. |
9 | Restart Auto Negotiation | 0, RW/SC | Restart Auto-Negotiation: 1 = Restart Auto-Negotiation. Re-initiates the Auto-Negotiation process. If Auto-Negotiation is disabled (bit 12 = 0), this bit is ignored. This bit is self-clearing and will return a value of 1 until Auto-Negotiation is initiated, whereupon it will self-clear. Operation of the Auto-Negotiation process is not affected by the management entity clearing this bit. 0 = Normal operation. |
8 | Duplex Mode | RW | Duplex Mode: When auto-negotiation is disabled writing to this bit allows the port Duplex capability to be selected. 1 = Full Duplex operation. 0 = Half Duplex operation. |
Bit | Bit Name | Default | Description |
7 | Collision Test | 0, RW | Collision Test: 1 = Collision test enabled. 0 = Normal operation. When set, this bit will cause the COL signal to be asserted in response to the assertion of TX_EN within 512-bit times. The COL signal will be deasserted within 4-bit times in response to the deassertion of TX_EN. |
6:0 | RESERVED | 0, RO | RESERVED: Write ignored, read as 0 |
关于以太网芯片寄存器的详细描述可参考该博客 http://blog.csdn.net/subfate/article/details/44958597
Linux中通过程序来读取寄存器当前的值:源代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define reteck(ret) \ if(ret < 0){ \ printf("%m! \"%s\" : line: %d\n", __func__, __LINE__); \ goto lab; \ } #define help() \ printf("mdio:\n"); \ printf("read operation: mdio reg_addr\n"); \ printf("write operation: mdio reg_addr value\n"); \ printf("For example:\n"); \ printf("mdio eth0 1\n"); \ printf("mdio eth0 0 0x12\n\n"); \ exit(0); int sockfd; int main(int argc, char *argv[]){ if(argc == 1 || !strcmp(argv[1], "-h")){ help(); } struct mii_ioctl_data *mii = NULL; struct ifreq ifr; int ret; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, argv[1], IFNAMSIZ - 1); sockfd = socket(PF_LOCAL, SOCK_DGRAM, 0); reteck(sockfd); //get phy address in smi bus ret = ioctl(sockfd, SIOCGMIIPHY, &ifr); reteck(ret); mii = (struct mii_ioctl_data*)&ifr.ifr_data; if(argc == 3){ mii->reg_num = (uint16_t)strtoul(argv[2], NULL, 0); ret = ioctl(sockfd, SIOCGMIIREG, &ifr); reteck(ret); printf("read phy addr: 0x%x reg: 0x%x value : 0x%x\n\n", mii->phy_id, mii->reg_num, mii->val_out); }else if(argc == 4){ mii->reg_num = (uint16_t)strtoul(argv[2], NULL, 0); mii->val_in = (uint16_t)strtoul(argv[3], NULL, 0); ret = ioctl(sockfd, SIOCSMIIREG, &ifr); reteck(ret); printf("write phy addr: 0x%x reg: 0x%x value : 0x%x\n\n", mii->phy_id, mii->reg_num, mii->val_in); } lab: close(sockfd); return 0; }
通过对PHY层 的寄存器来判断网卡的工作状态。
./phy eth0 0x1
./phy eth0 0x1 0x7849 将0x7849写入寄存器1
以上就是我对AT91SAM9260网卡驱动以及DP83848网卡芯片的一些理解。