/*
* Copyright (c) 2014-2015 Hisilicon Limited.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/etherdevice.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include "hns_enet.h"
#define HNS_PHY_PAGE_MDIX 0
#define HNS_PHY_PAGE_LED 3
#define HNS_PHY_PAGE_COPPER 0
#define HNS_PHY_PAGE_REG 22 /* Page Selection Reg. */
#define HNS_PHY_CSC_REG 16 /* Copper Specific Control Register */
#define HNS_PHY_CSS_REG 17 /* Copper Specific Status Register */
#define HNS_LED_FC_REG 16 /* LED Function Control Reg. */
#define HNS_LED_PC_REG 17 /* LED Polarity Control Reg. */
#define HNS_LED_FORCE_ON 9
#define HNS_LED_FORCE_OFF 8
#define HNS_CHIP_VERSION 660
#define HNS_NET_STATS_CNT 26
#define PHY_MDIX_CTRL_S (5)
#define PHY_MDIX_CTRL_M (3 << PHY_MDIX_CTRL_S)
#define PHY_MDIX_STATUS_B (6)
#define PHY_SPEED_DUP_RESOLVE_B (11)
/**
*hns_nic_get_link - get current link status
*@net_dev: net_device
*retuen 0 - success , negative --fail
*/
static u32 hns_nic_get_link(struct net_device *net_dev)
{
struct hns_nic_priv *priv = netdev_priv(net_dev);
u32 link_stat = priv->link;
struct hnae_handle *h;
assert(priv && priv->ae_handle);
h = priv->ae_handle;
if (priv->phy) {
if (!genphy_update_link(priv->phy))
link_stat = priv->phy->link;
else
link_stat = 0;
}
if (h->dev && h->dev->ops && h->dev->ops->get_status)
link_stat = link_stat && h->dev->ops->get_status(h);
else
link_stat = 0;
return link_stat;
}
static void hns_get_mdix_mode(struct net_device *net_dev,
struct ethtool_cmd *cmd)
{
int mdix_ctrl, mdix, retval, is_resolved;
struct hns_nic_priv *priv = netdev_priv(net_dev);
struct phy_device *phy_dev = priv->phy;
if (!phy_dev || !phy_dev->bus) {
cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID;
cmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
return;
}
(void)mdiobus_write(phy_dev->bus, phy_dev->addr, HNS_PHY_PAGE_REG,
HNS_PHY_PAGE_MDIX);
retval = mdiobus_read(phy_dev->bus, phy_dev->addr, HNS_PHY_CSC_REG);
mdix_ctrl = hnae_get_field(retval, PHY_MDIX_CTRL_M, PHY_MDIX_CTRL_S);
retval = mdiobus_read(phy_dev->bus, phy_dev->addr, HNS_PHY_CSS_REG);
mdix = hnae_get_bit(retval, PHY_MDIX_STATUS_B);
is_resolved = hnae_get_bit(retval, PHY_SPEED_DUP_RESOLVE_B);
(void)mdiobus_write(phy_dev->bus, phy_dev->addr, HNS_PHY_PAGE_REG,
HNS_PHY_PAGE_COPPER);
switch (mdix_ctrl) {
case 0x0:
cmd->eth_tp_mdix_ctrl = ETH_TP_MDI;
break;
case 0x1:
cmd->eth_tp_mdix_ctrl = ET