From: Girish K S
Added support for the EEE(Energy Efficient Ethernet) in 10G ethernet driver.
Signed-off-by: Girish K S
Neatening-by: Joe Perches
Signed-off-by: Byungho An
---
drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h | 53 +++
drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c| 86 +-
drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c | 47 ++
drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c| 165 +++-
.../net/ethernet/samsung/sxgbe/sxgbe_platform.c|4 +
drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h |5 +
6 files changed, 358 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
index f8ba7e4..5f1d02c 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
@@ -115,6 +115,33 @@ struct sxgbe_mtl_ops;
#define RX_PTP_SIGNAL 0x0A
#define RX_PTP_RESV_MSG0x0F
+/* EEE-LPI mode flags*/
+#define TX_ENTRY_LPI_MODE 0x10
+#define TX_EXIT_LPI_MODE 0x20
+#define RX_ENTRY_LPI_MODE 0x40
+#define RX_EXIT_LPI_MODE 0x80
+
+/* EEE-LPI Interrupt status flag */
+#define LPI_INT_STATUS BIT(5)
+
+/* EEE-LPI Default timer values */
+#define LPI_LINK_STATUS_TIMER 0x3E8
+#define LPI_MAC_WAIT_TIMER 0x00
+
+/* EEE-LPI Control and status definitions */
+#define LPI_CTRL_STATUS_TXABIT(19)
+#define LPI_CTRL_STATUS_PLSDIS BIT(18)
+#define LPI_CTRL_STATUS_PLSBIT(17)
+#define LPI_CTRL_STATUS_LPIEN BIT(16)
+#define LPI_CTRL_STATUS_TXRSTP BIT(11)
+#define LPI_CTRL_STATUS_RXRSTP BIT(10)
+#define LPI_CTRL_STATUS_RLPIST BIT(9)
+#define LPI_CTRL_STATUS_TLPIST BIT(8)
+#define LPI_CTRL_STATUS_RLPIEX BIT(3)
+#define LPI_CTRL_STATUS_RLPIEN BIT(2)
+#define LPI_CTRL_STATUS_TLPIEX BIT(1)
+#define LPI_CTRL_STATUS_TLPIEN BIT(0)
+
enum dma_irq_status {
tx_hard_error = BIT(0),
tx_bump_tc = BIT(1),
@@ -199,6 +226,13 @@ struct sxgbe_extra_stats {
unsigned long rx_buffer_access_err;
unsigned long rx_data_transfer_err;
+ /* EEE-LPI stats */
+ unsigned long tx_lpi_entry_n;
+ unsigned long tx_lpi_exit_n;
+ unsigned long rx_lpi_entry_n;
+ unsigned long rx_lpi_exit_n;
+ unsigned long eee_wakeup_error_n;
+
/* RX specific */
/* L2 error */
unsigned long rx_code_gmii_err;
@@ -296,6 +330,13 @@ struct sxgbe_core_ops {
unsigned char feature_index);
/* adjust SXGBE speed */
void (*set_speed)(void __iomem *ioaddr, unsigned char speed);
+
+ /* EEE-LPI specific operations */
+ void (*set_eee_mode)(void __iomem *ioaddr);
+ void (*reset_eee_mode)(void __iomem *ioaddr);
+ void (*set_eee_timer)(void __iomem *ioaddr, const int ls,
+ const int tw);
+ void (*set_eee_pls)(void __iomem *ioaddr, const int link);
};
const struct sxgbe_core_ops *sxgbe_get_core_ops(void);
@@ -352,6 +393,8 @@ struct sxgbe_hw_features {
/* IEEE 1588-2008 */
unsigned int atime_stamp;
+ unsigned int eee;
+
unsigned int tx_csum_offload;
unsigned int rx_csum_offload;
unsigned int multi_macaddr;
@@ -435,6 +478,13 @@ struct sxgbe_priv_data {
/* tc control */
int tx_tc;
int rx_tc;
+ /* EEE-LPI specific members */
+ struct timer_list eee_ctrl_timer;
+ bool tx_path_in_lpi_mode;
+ int lpi_irq;
+ int eee_enabled;
+ int eee_active;
+ int tx_lpi_timer;
};
/* Function prototypes */
@@ -457,4 +507,7 @@ int sxgbe_restore(struct net_device *ndev);
const struct sxgbe_mtl_ops *sxgbe_get_mtl_ops(void);
+void sxgbe_disable_eee_mode(struct sxgbe_priv_data * const priv);
+bool sxgbe_eee_init(struct sxgbe_priv_data * const priv);
+
#endif /* __SXGBE_COMMON_H__ */
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c
b/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c
index 17eea58..bf93b16 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c
@@ -47,11 +47,38 @@ static void sxgbe_core_dump_regs(void __iomem *ioaddr)
{
}
+static int sxgbe_get_lpi_status(void __iomem *ioaddr, const u32 irq_status)
+{
+ int status = 0;
+ int lpi_status;
+
+ /* Reading this register shall clear all the LPI status bits */
+ lpi_status = readl(ioaddr + SXGBE_CORE_LPI_CTRL_STATUS);
+
+ if (lpi_status & LPI_CTRL_STATUS_TLPIEN)
+ status |= TX_ENTRY_LPI_MODE;
+ if (lpi_status & LPI_CTRL_STATUS_TLPIEX)
+ status |= TX_EXIT_LPI_MODE;
+ if (lpi_status & LPI_CTRL_STATUS_RLPIEN)
+ status |= RX_ENTRY_LPI_MODE;
+ if (lpi_status & LPI_CTRL_STATUS_RLPIEX)
+ status |= RX_EXIT_LPI_MODE;
+
+ return status;
+}
+
/* Handle extra events on specific interrup