没有物理层的PHY芯片,也就是无法使用MDIO接口配置IEEE相关的寄存器。
有时我们只要板子内两个CPU或者FPGA与CPU间进行点对点通信,那就无需使用PHY和变压器了!节省成本
比较新的linux内核能直接支持这种应用,即所谓的fixed-link。
下面的例子是TI am3358官方评估板BBB版的设备树摘录:
红色为关注点
cpsw_default: cpsw_default {
pinctrl-single,pins = <
/* Slave 1 */
0x110 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxerr.mii1_rxerr */
0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txen.mii1_txen */
0x118 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxdv.mii1_rxdv */
0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd3.mii1_txd3 */
0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd2.mii1_txd2 */
0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd1.mii1_txd1 */
0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd0.mii1_txd0 */
0x12c (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_txclk.mii1_txclk */
0x130 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxclk.mii1_rxclk */
0x134 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd3.mii1_rxd3 */
0x138 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd2.mii1_rxd2 */
0x13c (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd1.mii1_rxd1 */
0x140 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd0.mii1_rxd0 */
//for MAC FPGA test
/* Slave 2 */
//RGMII
//0x58 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_a6.mii2_txclk.rgmii2_tclk */
//0x5c (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_a7.mii2_rxclk.rgmii2_rclk */
//0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a0.mii2_txen.rgmii2_tctl */
//0x48 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a2.mii2_txd3.rgmii2_td3 */
//0x4c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a3.mii2_txd2.rgmii2_td2 */
//0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a4.mii2_txd1.rgmii2_td1 */
//0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a5.mii2_txd0.rgmii2_td0 */
//0x44 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_a1.mii2_rxdv.rgmii2_rctl */
//0x60 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_a8.mii2_rxd3.rgmii2_rd3 */
//0x64 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_a9.mii2_rxd2.rgmii2_rd2 */
//0x68 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_a10.mii2_rxd1.rgmii2_rd1 */
//0x6c (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_a11.mii2_rxd0.rgmii2_rd0 */
//MII
0x58 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a6.mii2_txclk */
0x5c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a7.mii2_rxclk */
0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_a0.mii2_txen */
0x48 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_a2.mii2_txd3 */
0x4c (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_a3.mii2_txd2 */
0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_a4.mii2_txd1 */
0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* gpmc_a5.mii2_txd0 */
0x44 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a1.mii2_rxdv */
0x60 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a8.mii2_rxd3 */
0x64 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a9.mii2_rxd2 */
0x68 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a10.mii2_rxd1 */
0x6c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a11.mii2_rxd0 */
//0x74 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_wpn.mii2_rxerr */
//0x78 (PIN_INPUT_PULLDOWN | MUX_MODE1) /* gpmc_ben1.mii2_col */
//0x70 (PIN_INPUT_PULLDOWN | MUX_MODE1) /* gpmc_wait0.mii2_crs */
>;
};
&cpsw_emac1 {
//phy_id = <&davinci_mdio>, <0>;
phy-mode = "mii"; //phy-mode = "rgmii-txid";
dual_emac_res_vlan = <2>;
fixed-link {
speed = <100>; //speed = <1000>;
full-duplex;
//pause;
//asym-pause;
};
};
&mac {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
dual_emac; //for MAC FPGA test
status = "okay";
};
aliases {
i2c0 = &i2c0;
i2c1 = &i2c1;
i2c2 = &i2c2;
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
serial3 = &uart3;
serial4 = &uart4;
serial5 = &uart5;
d_can0 = &dcan0;
d_can1 = &dcan1;
usb0 = &usb0;
usb1 = &usb1;
phy0 = &usb0_phy;
phy1 = &usb1_phy;
ethernet0 = &cpsw_emac0;
//for MAC FPGA test
ethernet1 = &cpsw_emac1;
};
mac: ethernet@4a100000 {
compatible = "ti,am335x-cpsw","ti,cpsw";
ti,hwmods = "cpgmac0";
clocks = <&cpsw_125mhz_gclk>, <&cpsw_cpts_rft_clk>;
clock-names = "fck", "cpts";
cpdma_channels = <8>;
ale_entries = <1024>;
bd_ram_size = <0x2000>;
no_bd_ram = <0>;
mac_control = <0x20>;
slaves = <2>; //for MAC FPGA test
active_slave = <0>;
cpts_clock_mult = <0x80000000>;
cpts_clock_shift = <29>;
reg = <0x4a100000 0x800
0x4a101200 0x100>;
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&intc>;
/*
* c0_rx_thresh_pend
* c0_rx_pend
* c0_tx_pend
* c0_misc_pend
*/
interrupts = <40 41 42 43>;
ranges;
syscon = <&scm_conf>;
status = "disabled";
davinci_mdio: mdio@4a101000 {
compatible = "ti,cpsw-mdio";
#address-cells = <1>;
#size-cells = <0>;
ti,hwmods = "davinci_mdio";
bus_freq = <1000000>;
reg = <0x4a101000 0x100>;
status = "disabled";
};
cpsw_emac0: slave@4a100200 {
/* Filled in by U-Boot */
mac-address = [ 00 00 00 00 00 00 ];
};
cpsw_emac1: slave@4a100300 {
/* Filled in by U-Boot */
mac-address = [ 00 00 00 00 00 00 ];
};
phy_sel: cpsw-phy-sel@44e10650 {
compatible = "ti,am3352-cpsw-phy-sel";
reg= <0x44e10650 0x4>;
reg-names = "gmii-sel";
};
};
另一个佐证是海思Hi3559av100的设备树:hi3559av100-demb.dts
&mdio {
ethphy: ethernet-phy@0 {
reg = <0>;
};
};
/*&mdio1 {
ethphy1: ethernet-phy@3 {
reg = <3>;
};
};*/
&higmac {
phy-handle = <ðphy>;
phy-mode = "rgmii";
};
&higmac1 {
//phy-handle = <ðphy1>;
phy-mode = "mii"; //"rgmii"
fixed-link {
speed = <100>; //or when RGMII using 1000
full-duplex;
//pause;
//asym-pause;
};
};
至于fixed-link在内核里怎么实现可以自行阅读源码,但可以理解的是,芯片厂商必须移植好MAC控制器驱动,使得支持fixed-link譬如有如下代码:
/* check if a fixed-link is defined in device-tree */
if (of_phy_is_fixed_link(node)) {
ret = of_phy_register_fixed_link(node);
...
比较旧的linux内核没有fixed-link,也无需灰心。屏蔽掉MDIO read和write操作PHY的部分,让其以为有一个dummy的PHY,并且总是设置成功,具体情况要具体分析。
//FPGA提供时钟,测试发送
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
int sockfd;
struct sockaddr_in des_addr;
int r;
char sendline[1024] = {"hello"};
const int on = 1;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
bzero(&des_addr, sizeof(des_addr));
des_addr.sin_family = AF_INET;
des_addr.sin_addr.s_addr = inet_addr("192.168.20.255"); //广播地址 根据你ifconfig配置的ip网段设置,xxx.xxx.xxx.255
des_addr.sin_port = htons(9999);
while(1)
{
r = sendto(sockfd, sendline, strlen(sendline), 0, (struct sockaddr*)&des_addr, sizeof(des_addr));
if (r <= 0)
{
perror("sendto error");
exit(-1);
}
}
...
...