/* * Copyright (c) Company 2018-2019. All rights reserved. * Description: autoeee.c */ #include #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); }