以太网mac地址
dwmac-rk.c
static int rk_gmac_probe(struct platform_device *pdev)
{
plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); // 刷机第一次 由uboot env 传入
plat_dat->get_eth_addr = rk_get_eth_addr; //判断是否有mac ,是否需要从vendor获取
......
ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (ret)
goto err_gmac_powerdown;
}
stmmac_main.c
int stmmac_dvr_probe(struct device *device,
struct plat_stmmacenet_data *plat_dat,
struct stmmac_resources *res)
{
if (res->mac)
memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN);
pr_info("%s aaaaaaaaaaaa: device MAC address %pM\n", priv->dev->name,priv->dev->dev_addr);
dev_set_drvdata(device, priv->dev);
.....
stmmac_check_ether_addr(priv);
....
}
/**
* stmmac_check_ether_addr - check if the MAC addr is valid
* @priv: driver private structure
* Description:
* it is to verify if the MAC address is valid, in case of failures it
* generates a random MAC address
*/
static void stmmac_check_ether_addr(struct stmmac_priv *priv)
{
printk("%s\n\n\n ",__func__);
if (!is_valid_ether_addr(priv->dev->dev_addr)) {
priv->hw->mac->get_umac_addr(priv->hw,
priv->dev->dev_addr, 0);
pr_info("%s:000000000000 device MAC address %pM\n", priv->dev->name,
priv->dev->dev_addr);
if (likely(priv->plat->get_eth_addr))
priv->plat->get_eth_addr(priv->plat->bsp_priv,
priv->dev->dev_addr);
if (!is_valid_ether_addr(priv->dev->dev_addr))
eth_hw_addr_random(priv->dev);
pr_info("%s: device MAC address %pM\n", priv->dev->name,
priv->dev->dev_addr);
}
pr_info("%s 222222222222: device MAC address %pM\n", priv->dev->name,priv->dev->dev_addr);
}
以下是分成这两条支线解析
stmmac_platform.c
struct plat_stmmacenet_data *stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
{
*mac = of_get_mac_address(np);
....
}
static const void *of_get_mac_addr(struct device_node *np, const char *name)
{
struct property *pp = of_find_property(np, name, NULL);
if (pp && pp->length == ETH_ALEN && is_valid_ether_addr(pp->value)){
printk("%s : device pp MAC address %pM \n\n",__func__,pp->value);
return pp->value;
}
return NULL;
}
/**
* Search the device tree for the best MAC address to use. 'mac-address' is
* checked first, because that is supposed to contain to "most recent" MAC
* address. If that isn't set, then 'local-mac-address' is checked next,
* because that is the default address. If that isn't set, then the obsolete
* 'address' is checked, just in case we're using an old device tree.
*
* Note that the 'address' property is supposed to contain a virtual address of
* the register set, but some DTS files have redefined that property to be the
* MAC address.
*
* All-zero MAC addresses are rejected, because those could be properties that
* exist in the device tree, but were not set by U-Boot. For example, the
* DTS could define 'mac-address' and 'local-mac-address', with zero MAC
* addresses. Some older U-Boots only initialized 'local-mac-address'. In
* this case, the real MAC is in 'local-mac-address', and 'mac-address' exists
* but is all zeros.
*/
const void *of_get_mac_address(struct device_node *np)
{
const void *addr;
addr = of_get_mac_addr(np, "mac-address");
printk("%s : device mac-address %pM \n\n",__func__,addr);
if (addr)
return addr;
addr = of_get_mac_addr(np, "local-mac-address"); ***//由uboot传入 dts找不到这个node***
printk("%s : device local-mac-address %pM \n\n",__func__,addr);
if (addr)
return addr;
return of_get_mac_addr(np, "address");
}
EXPORT_SYMBOL(of_get_mac_address);
Uboot 代码:
/Project1/rk3399pro/u-boot/common/fdt_support.c
void fdt_fixup_ethernet(void *fdt)
{
int i = 0, j, prop;
char *tmp, *end;
char mac[16];
const char *path;
unsigned char mac_addr[ARP_HLEN];
int offset;
#ifdef FDT_SEQ_MACADDR_FROM_ENV
int nodeoff;
const struct fdt_property *fdt_prop;
#endif
if (fdt_path_offset(fdt, "/aliases") < 0)
return;
/* Cycle through all aliases */
for (prop = 0; ; prop++) {
const char *name;
/* FDT might have been edited, recompute the offset */
offset = fdt_first_property_offset(fdt,
fdt_path_offset(fdt, "/aliases"));
/* Select property number 'prop' */
for (j = 0; j < prop; j++)
offset = fdt_next_property_offset(fdt, offset);
if (offset < 0)
break;
path = fdt_getprop_by_offset(fdt, offset, &name, NULL);
if (!strncmp(name, "ethernet", 8)) {
/* Treat plain "ethernet" same as "ethernet0". */
if (!strcmp(name, "ethernet")
#ifdef FDT_SEQ_MACADDR_FROM_ENV
|| !strcmp(name, "ethernet0")
#endif
)
i = 0;
#ifndef FDT_SEQ_MACADDR_FROM_ENV
else
i = trailing_strtol(name);
#endif
if (i != -1) {
if (i == 0)
strcpy(mac, "ethaddr");
else
sprintf(mac, "eth%daddr", i);
} else {
continue;
}
#ifdef FDT_SEQ_MACADDR_FROM_ENV
nodeoff = fdt_path_offset(fdt, path);
fdt_prop = fdt_get_property(fdt, nodeoff, "status",
NULL);
if (fdt_prop && !strcmp(fdt_prop->data, "disabled"))
continue;
i++;
#endif
tmp = env_get(mac);
if (!tmp)
continue;
printf("%s 222222222222: device MAC address %pM\n",__func__, tmp);
for (j = 0; j < 6; j++) {
mac_addr[j] = tmp ?
simple_strtoul(tmp, &end, 16) : 0; //将获到的env char 转成16进制
if (tmp)
tmp = (*end) ? end + 1 : end;
}
do_fixup_by_path(fdt, path, "mac-address",
&mac_addr, 6, 0);
do_fixup_by_path(fdt, path, "local-mac-address",
&mac_addr, 6, 1);
printf("%s 222222222222: device MAC address %pM\n",__func__, mac_addr);
}
==============================================================================================================
第二方式,从vendor获取的方法:
dwmac-rk.c
void rk_get_eth_addr(void *priv, unsigned char *addr)
{
int ret;
struct rk_priv_data *bsp_priv = priv;
struct device *dev = &bsp_priv->pdev->dev;
printk("%s \n\n",__func__);
rk_devinfo_get_eth_mac(addr);
if (is_valid_ether_addr(addr))
goto out;
ret = rk_vendor_read(LAN_MAC_ID, addr, 6); //LAN_MAC_ID 3
if (ret != 6 || is_zero_ether_addr(addr)) {
dev_err(dev, "%s: rk_vendor_read eth mac address failed (%d)",
__func__, ret);
random_ether_addr(addr); //随机产生一个mac地址
dev_err(dev, "%s: generate random eth mac address: %02x:%02x:%02x:%02x:%02x:%02x",__func__, addr[0], addr[1], addr[2],
addr[3], addr[4], addr[5]);
ret = rk_vendor_write(LAN_MAC_ID, addr, 6);
if (ret != 0)
dev_err(dev, "%s: rk_vendor_write eth mac address failed (%d)",__func__, ret);
}
printk( "%s: generate random eth mac address: %02x:%02x:%02x:%02x:%02x:%02x \n\n",__func__, addr[0], addr[1], addr[2],
addr[3], addr[4], addr[5]);
out:
dev_err(dev, "%s: mac address: %02x:%02x:%02x:%02x:%02x:%02x",__func__, addr[0], addr[1], addr[2],
addr[3], addr[4], addr[5]);
}