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
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);
|
|
}
|