RTEMS network driver port-MDIO communication
First look at the connection between bbb board processor and network card :
To be clear, bbb board am3359 processor is comes with MAC.
The figure can be seen, the processor and network card connection is GMII way, using MDIO and network card control register to communicate.
First understand how uboot achieve mdio communication.
View uboot source code, first check the network card registration and initialization methods:
Uboot After starting.s starts the function that was first called on the hardware initialization is the eth_initialize function:
Function called eth_common_init function, the function is as follows:
Where the miiphy_init function is a registered mii device that lets it join the linked list.
Then call phy_init function, the function of the network card device for the registration and initialization:
the network card lan8710 is smsc company, select phy_smsc_init function to compile:
The function is implemented as follows:
You can see for the lan8710a network card phy_register, that is, the network card device to join the linked list.
Then go back to the eth_common_init function and execute the board_eth_init function down:
The function is defined in the board.c file, including the bbb board specific configuration process, very important
The concrete realization is as follows:
Analyze the function:
First read the mac address, and then set it as an environment variable, easy to view in the command line.
(MII_MODE_ENABLE, & cdev-> miisel), call this system io function, the MII_MODE_ENABLE macro definition of the corresponding value written to & cdev-> miisel this register, and the register address is CTRL_DEVICE_BASE + miisel , That is, CTRL_DEVICE_BASE the basic address plus miisel offset, CTRL_DEVICE_BASE the macro value is 0x4A101000, defined in the arch / arm / include / asm / arch-am33xx / hardware_am33xx.h file.
After enabling, board_eth_init continues to call the cpsw_register function. In this function, it will communicate with the network card mdio to view the network card ID in the network card register.
The specific function is in the /drivers/net/phy/phy.c file:
The registers of the NIC are IDID and PHYSID2, so they need to read these two registers.
The specific instructions for implementing the read register are: bus-> read (bus, addr, devad, MII_PHYSID1)
This bus read function is actually CPSW_mdio_read function, as follows:
In this function, the wait_for_user_access function is called first:
The function of the function is to constantly read a card register value, to determine whether access, if you can return to non-0 value, or return a negative number.
And then return to the above function, call the __raw_writel function to write the value of the register, the value reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) | (phy_id << 16)); said to communicate and read the register , So that the network card to be prepared.
Register address is & mdio_regs-> user  .access, after writing, continue to call reg = wait_for_user_access (); read the value of the register.
And then return the reg value to judge: data = (reg & USERACCESS_ACK)? (Reg & USERACCESS_DATA): -1;
If reg & USERACCESS_ACK is positive, that is, the network card register to make a response, that data is right, then reg & USERACCESS_DATA, its assignment to the data. Otherwise the data assignment is -1, indicating that no data is being read.
Read the register and return to the get_phy_id function, phy_reg = bus-> read (bus, addr, devad, MII_PHYSID1);
This time the value of phy_reg is the value of the register being read
Then read the next register: phy_reg = bus-> read (bus, addr, devad, MII_PHYSID2);
Because the network card id a register fit, divided into two registers. After the two registers are read, a simple operation can be a complete network card ID.