You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
2.7 KiB

/*
* Copyright (c) Company 2018-2019. All rights reserved.
* Description: autoeee.c
*/
#include <linux/phy.h>
#include "gmac.h"
#include "autoeee.h"
void init_autoeee(struct gmac_netdev_local *ld)
{
unsigned int phy_id;
int eee_available, lp_eee_capable;
unsigned int v;
struct phy_info *phy_info = NULL;
unsigned int link_stat = 0;
if (ld == NULL || ld->phy == NULL)
return;
if (ld->eee_init != NULL)
goto eee_init;
phy_id = ld->phy->phy_id;
phy_info = phy_search_ids(phy_id);
if (phy_info != NULL) {
eee_available = phy_info->eee_available;
if (netif_msg_wol(ld))
pr_info("fit phy_id:0x%x, phy_name:%s, eee:%d\n", phy_info->phy_id, phy_info->name, eee_available);
if (eee_available == 0)
goto not_support;
if (eee_available == PHY_EEE) {
if (netif_msg_wol(ld))
pr_info("enter phy-EEE mode\n");
v = readl(ld->gmac_iobase + EEE_ENABLE);
v &= ~BIT_EEE_ENABLE; /* disable auto-EEE */
writel(v, ld->gmac_iobase + EEE_ENABLE);
return;
}
ld->eee_init = phy_info->eee_init;
eee_init:
switch (ld->phy->speed) {
case SPEED_10:
link_stat |= GMAC_SPD_10M;
break;
case SPEED_100:
link_stat |= GMAC_SPD_100M;
break;
case SPEED_1000:
link_stat |= GMAC_SPD_1000M;
break;
default:
break;
}
lp_eee_capable = ld->eee_init(ld->phy);
if (ld->phy->link) {
if ((unsigned int)lp_eee_capable & link_stat) {
/* EEE_1us: 0x7c for 125M */
writel(0x7c, ld->gmac_iobase + EEE_TIME_CLK_CNT);
writel(0x1e0400, ld->gmac_iobase + EEE_TIMER);
v = readl(ld->gmac_iobase + EEE_LINK_STATUS);
v |= 0x3 << 1; /* auto EEE and ... */
v |= BIT_PHY_LINK_STATUS; /* phy linkup */
writel(v, ld->gmac_iobase + EEE_LINK_STATUS);
v = readl(ld->gmac_iobase + EEE_ENABLE);
v |= BIT_EEE_ENABLE; /* enable EEE */
writel(v, ld->gmac_iobase + EEE_ENABLE);
if (netif_msg_wol(ld))
pr_info("enter auto-EEE mode\n");
} else {
if (netif_msg_wol(ld))
pr_info("link partner not support EEE\n");
}
} else {
v = readl(ld->gmac_iobase + EEE_LINK_STATUS);
v &= ~(BIT_PHY_LINK_STATUS); /* phy linkdown */
writel(v, ld->gmac_iobase + EEE_LINK_STATUS);
}
return;
}
not_support:
ld->eee_init = NULL;
if (netif_msg_wol(ld))
pr_info("non-EEE mode\n");
}
void eee_phy_linkdown(const struct gmac_netdev_local *ld)
{
unsigned int v;
if (ld == NULL)
return;
v = readl(ld->gmac_iobase + EEE_LINK_STATUS);
/* update phy link state */
v &= ~BIT_PHY_LINK_STATUS;
writel(v, ld->gmac_iobase + EEE_LINK_STATUS);
}
void eee_phy_linkup(const struct gmac_netdev_local *ld)
{
unsigned int v;
if (ld == NULL)
return;
v = readl(ld->gmac_iobase + EEE_LINK_STATUS);
/* update phy link state */
v |= BIT_PHY_LINK_STATUS;
writel(v, ld->gmac_iobase + EEE_LINK_STATUS);
}