Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 314942
b: refs/heads/master
c: d765955
h: refs/heads/master
v: v3
  • Loading branch information
Giuseppe CAVALLARO authored and David S. Miller committed Jul 1, 2012
1 parent 9b3d224 commit bec1376
Show file tree
Hide file tree
Showing 10 changed files with 373 additions and 19 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0ec2ccd0804ebb57a860c59d056a3f420c4f8028
refs/heads/master: d765955d2ae0b88781a0db3a5bacfe4241925e09
31 changes: 30 additions & 1 deletion trunk/drivers/net/ethernet/stmicro/stmmac/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,16 @@ struct stmmac_extra_stats {
unsigned long poll_n;
unsigned long sched_timer_n;
unsigned long normal_irq_n;
unsigned long mmc_tx_irq_n;
unsigned long mmc_rx_irq_n;
unsigned long mmc_rx_csum_offload_irq_n;
/* EEE */
unsigned long irq_receive_pmt_irq_n;
unsigned long irq_tx_path_in_lpi_mode_n;
unsigned long irq_tx_path_exit_lpi_mode_n;
unsigned long irq_rx_path_in_lpi_mode_n;
unsigned long irq_rx_path_exit_lpi_mode_n;
unsigned long phy_eee_wakeup_error_n;
};

/* CSR Frequency Access Defines*/
Expand Down Expand Up @@ -162,6 +172,17 @@ enum tx_dma_irq_status {
handle_tx_rx = 3,
};

enum core_specific_irq_mask {
core_mmc_tx_irq = 1,
core_mmc_rx_irq = 2,
core_mmc_rx_csum_offload_irq = 4,
core_irq_receive_pmt_irq = 8,
core_irq_tx_path_in_lpi_mode = 16,
core_irq_tx_path_exit_lpi_mode = 32,
core_irq_rx_path_in_lpi_mode = 64,
core_irq_rx_path_exit_lpi_mode = 128,
};

/* DMA HW capabilities */
struct dma_features {
unsigned int mbps_10_100;
Expand Down Expand Up @@ -208,6 +229,10 @@ struct dma_features {
#define MAC_ENABLE_TX 0x00000008 /* Transmitter Enable */
#define MAC_RNABLE_RX 0x00000004 /* Receiver Enable */

/* Default LPI timers */
#define STMMAC_DEFAULT_LIT_LS_TIMER 0x3E8
#define STMMAC_DEFAULT_TWT_LS_TIMER 0x0

struct stmmac_desc_ops {
/* DMA RX descriptor ring initialization */
void (*init_rx_desc) (struct dma_desc *p, unsigned int ring_size,
Expand Down Expand Up @@ -278,7 +303,7 @@ struct stmmac_ops {
/* Dump MAC registers */
void (*dump_regs) (void __iomem *ioaddr);
/* Handle extra events on specific interrupts hw dependent */
void (*host_irq_status) (void __iomem *ioaddr);
int (*host_irq_status) (void __iomem *ioaddr);
/* Multicast filter setting */
void (*set_filter) (struct net_device *dev, int id);
/* Flow control setting */
Expand All @@ -291,6 +316,10 @@ struct stmmac_ops {
unsigned int reg_n);
void (*get_umac_addr) (void __iomem *ioaddr, unsigned char *addr,
unsigned int reg_n);
void (*set_eee_mode) (void __iomem *ioaddr);
void (*reset_eee_mode) (void __iomem *ioaddr);
void (*set_eee_timer) (void __iomem *ioaddr, int ls, int tw);
void (*set_eee_pls) (void __iomem *ioaddr, int link);
};

struct mac_link {
Expand Down
20 changes: 20 additions & 0 deletions trunk/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

#define GMAC_INT_STATUS 0x00000038 /* interrupt status register */
enum dwmac1000_irq_status {
lpiis_irq = 0x400,
time_stamp_irq = 0x0200,
mmc_rx_csum_offload_irq = 0x0080,
mmc_tx_irq = 0x0040,
Expand All @@ -60,6 +61,25 @@ enum power_event {
power_down = 0x00000001,
};

/* Energy Efficient Ethernet (EEE)
*
* LPI status, timer and control register offset
*/
#define LPI_CTRL_STATUS 0x0030
#define LPI_TIMER_CTRL 0x0034

/* LPI control and status defines */
#define LPI_CTRL_STATUS_LPITXA 0x00080000 /* Enable LPI TX Automate */
#define LPI_CTRL_STATUS_PLSEN 0x00040000 /* Enable PHY Link Status */
#define LPI_CTRL_STATUS_PLS 0x00020000 /* PHY Link Status */
#define LPI_CTRL_STATUS_LPIEN 0x00010000 /* LPI Enable */
#define LPI_CTRL_STATUS_RLPIST 0x00000200 /* Receive LPI state */
#define LPI_CTRL_STATUS_TLPIST 0x00000100 /* Transmit LPI state */
#define LPI_CTRL_STATUS_RLPIEX 0x00000008 /* Receive LPI Exit */
#define LPI_CTRL_STATUS_RLPIEN 0x00000004 /* Receive LPI Entry */
#define LPI_CTRL_STATUS_TLPIEX 0x00000002 /* Transmit LPI Exit */
#define LPI_CTRL_STATUS_TLPIEN 0x00000001 /* Transmit LPI Entry */

/* GMAC HW ADDR regs */
#define GMAC_ADDR_HIGH(reg) (((reg > 15) ? 0x00000800 : 0x00000040) + \
(reg * 8))
Expand Down
101 changes: 93 additions & 8 deletions trunk/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,26 +194,107 @@ static void dwmac1000_pmt(void __iomem *ioaddr, unsigned long mode)
}


static void dwmac1000_irq_status(void __iomem *ioaddr)
static int dwmac1000_irq_status(void __iomem *ioaddr)
{
u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
int status = 0;

/* Not used events (e.g. MMC interrupts) are not handled. */
if ((intr_status & mmc_tx_irq))
CHIP_DBG(KERN_DEBUG "GMAC: MMC tx interrupt: 0x%08x\n",
if ((intr_status & mmc_tx_irq)) {
CHIP_DBG(KERN_INFO "GMAC: MMC tx interrupt: 0x%08x\n",
readl(ioaddr + GMAC_MMC_TX_INTR));
if (unlikely(intr_status & mmc_rx_irq))
CHIP_DBG(KERN_DEBUG "GMAC: MMC rx interrupt: 0x%08x\n",
status |= core_mmc_tx_irq;
}
if (unlikely(intr_status & mmc_rx_irq)) {
CHIP_DBG(KERN_INFO "GMAC: MMC rx interrupt: 0x%08x\n",
readl(ioaddr + GMAC_MMC_RX_INTR));
if (unlikely(intr_status & mmc_rx_csum_offload_irq))
CHIP_DBG(KERN_DEBUG "GMAC: MMC rx csum offload: 0x%08x\n",
status |= core_mmc_rx_irq;
}
if (unlikely(intr_status & mmc_rx_csum_offload_irq)) {
CHIP_DBG(KERN_INFO "GMAC: MMC rx csum offload: 0x%08x\n",
readl(ioaddr + GMAC_MMC_RX_CSUM_OFFLOAD));
status |= core_mmc_rx_csum_offload_irq;
}
if (unlikely(intr_status & pmt_irq)) {
CHIP_DBG(KERN_DEBUG "GMAC: received Magic frame\n");
CHIP_DBG(KERN_INFO "GMAC: received Magic frame\n");
/* clear the PMT bits 5 and 6 by reading the PMT
* status register. */
readl(ioaddr + GMAC_PMT);
status |= core_irq_receive_pmt_irq;
}
/* MAC trx/rx EEE LPI entry/exit interrupts */
if (intr_status & lpiis_irq) {
/* Clean LPI interrupt by reading the Reg 12 */
u32 lpi_status = readl(ioaddr + LPI_CTRL_STATUS);

if (lpi_status & LPI_CTRL_STATUS_TLPIEN) {
CHIP_DBG(KERN_INFO "GMAC TX entered in LPI\n");
status |= core_irq_tx_path_in_lpi_mode;
}
if (lpi_status & LPI_CTRL_STATUS_TLPIEX) {
CHIP_DBG(KERN_INFO "GMAC TX exit from LPI\n");
status |= core_irq_tx_path_exit_lpi_mode;
}
if (lpi_status & LPI_CTRL_STATUS_RLPIEN) {
CHIP_DBG(KERN_INFO "GMAC RX entered in LPI\n");
status |= core_irq_rx_path_in_lpi_mode;
}
if (lpi_status & LPI_CTRL_STATUS_RLPIEX) {
CHIP_DBG(KERN_INFO "GMAC RX exit from LPI\n");
status |= core_irq_rx_path_exit_lpi_mode;
}
}

return status;
}

static void dwmac1000_set_eee_mode(void __iomem *ioaddr)
{
u32 value;

/* Enable the link status receive on RGMII, SGMII ore SMII
* receive path and instruct the transmit to enter in LPI
* state. */
value = readl(ioaddr + LPI_CTRL_STATUS);
value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
writel(value, ioaddr + LPI_CTRL_STATUS);
}

static void dwmac1000_reset_eee_mode(void __iomem *ioaddr)
{
u32 value;

value = readl(ioaddr + LPI_CTRL_STATUS);
value &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA);
writel(value, ioaddr + LPI_CTRL_STATUS);
}

static void dwmac1000_set_eee_pls(void __iomem *ioaddr, int link)
{
u32 value;

value = readl(ioaddr + LPI_CTRL_STATUS);

if (link)
value |= LPI_CTRL_STATUS_PLS;
else
value &= ~LPI_CTRL_STATUS_PLS;

writel(value, ioaddr + LPI_CTRL_STATUS);
}

static void dwmac1000_set_eee_timer(void __iomem *ioaddr, int ls, int tw)
{
int value = ((tw & 0xffff)) | ((ls & 0x7ff) << 16);

/* Program the timers in the LPI timer control register:
* LS: minimum time (ms) for which the link
* status from PHY should be ok before transmitting
* the LPI pattern.
* TW: minimum time (us) for which the core waits
* after it has stopped transmitting the LPI pattern.
*/
writel(value, ioaddr + LPI_TIMER_CTRL);
}

static const struct stmmac_ops dwmac1000_ops = {
Expand All @@ -226,6 +307,10 @@ static const struct stmmac_ops dwmac1000_ops = {
.pmt = dwmac1000_pmt,
.set_umac_addr = dwmac1000_set_umac_addr,
.get_umac_addr = dwmac1000_get_umac_addr,
.set_eee_mode = dwmac1000_set_eee_mode,
.reset_eee_mode = dwmac1000_reset_eee_mode,
.set_eee_timer = dwmac1000_set_eee_timer,
.set_eee_pls = dwmac1000_set_eee_pls,
};

struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr)
Expand Down
4 changes: 2 additions & 2 deletions trunk/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ static int dwmac100_rx_ipc_enable(void __iomem *ioaddr)
return 0;
}

static void dwmac100_irq_status(void __iomem *ioaddr)
static int dwmac100_irq_status(void __iomem *ioaddr)
{
return;
return 0;
}

static void dwmac100_set_umac_addr(void __iomem *ioaddr, unsigned char *addr,
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
#define DMA_INTR_DEFAULT_MASK (DMA_INTR_NORMAL | DMA_INTR_ABNORMAL)

/* DMA Status register defines */
#define DMA_STATUS_GLPII 0x40000000 /* GMAC LPI interrupt */
#define DMA_STATUS_GPI 0x10000000 /* PMT interrupt */
#define DMA_STATUS_GMI 0x08000000 /* MMC interrupt */
#define DMA_STATUS_GLI 0x04000000 /* GMAC Line interface int */
Expand Down
8 changes: 8 additions & 0 deletions trunk/drivers/net/ethernet/stmicro/stmmac/stmmac.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ struct stmmac_priv {
#endif
int clk_csr;
int synopsys_id;
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;
};

extern int phyaddr;
Expand All @@ -104,6 +110,8 @@ int stmmac_dvr_remove(struct net_device *ndev);
struct stmmac_priv *stmmac_dvr_probe(struct device *device,
struct plat_stmmacenet_data *plat_dat,
void __iomem *addr);
void stmmac_disable_eee_mode(struct stmmac_priv *priv);
bool stmmac_eee_init(struct stmmac_priv *priv);

#ifdef CONFIG_HAVE_CLK
static inline int stmmac_clk_enable(struct stmmac_priv *priv)
Expand Down
57 changes: 57 additions & 0 deletions trunk/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,16 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
STMMAC_STAT(poll_n),
STMMAC_STAT(sched_timer_n),
STMMAC_STAT(normal_irq_n),
STMMAC_STAT(normal_irq_n),
STMMAC_STAT(mmc_tx_irq_n),
STMMAC_STAT(mmc_rx_irq_n),
STMMAC_STAT(mmc_rx_csum_offload_irq_n),
STMMAC_STAT(irq_receive_pmt_irq_n),
STMMAC_STAT(irq_tx_path_in_lpi_mode_n),
STMMAC_STAT(irq_tx_path_exit_lpi_mode_n),
STMMAC_STAT(irq_rx_path_in_lpi_mode_n),
STMMAC_STAT(irq_rx_path_exit_lpi_mode_n),
STMMAC_STAT(phy_eee_wakeup_error_n),
};
#define STMMAC_STATS_LEN ARRAY_SIZE(stmmac_gstrings_stats)

Expand Down Expand Up @@ -366,6 +376,11 @@ static void stmmac_get_ethtool_stats(struct net_device *dev,
(*(u32 *)p);
}
}
if (priv->eee_enabled) {
int val = phy_get_eee_err(priv->phydev);
if (val)
priv->xstats.phy_eee_wakeup_error_n = val;
}
}
for (i = 0; i < STMMAC_STATS_LEN; i++) {
char *p = (char *)priv + stmmac_gstrings_stats[i].stat_offset;
Expand Down Expand Up @@ -464,6 +479,46 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
return 0;
}

static int stmmac_ethtool_op_get_eee(struct net_device *dev,
struct ethtool_eee *edata)
{
struct stmmac_priv *priv = netdev_priv(dev);

if (!priv->dma_cap.eee)
return -EOPNOTSUPP;

edata->eee_enabled = priv->eee_enabled;
edata->eee_active = priv->eee_active;
edata->tx_lpi_timer = priv->tx_lpi_timer;

return phy_ethtool_get_eee(priv->phydev, edata);
}

static int stmmac_ethtool_op_set_eee(struct net_device *dev,
struct ethtool_eee *edata)
{
struct stmmac_priv *priv = netdev_priv(dev);

priv->eee_enabled = edata->eee_enabled;

if (!priv->eee_enabled)
stmmac_disable_eee_mode(priv);
else {
/* We are asking for enabling the EEE but it is safe
* to verify all by invoking the eee_init function.
* In case of failure it will return an error.
*/
priv->eee_enabled = stmmac_eee_init(priv);
if (!priv->eee_enabled)
return -EOPNOTSUPP;

/* Do not change tx_lpi_timer in case of failure */
priv->tx_lpi_timer = edata->tx_lpi_timer;
}

return phy_ethtool_set_eee(priv->phydev, edata);
}

static const struct ethtool_ops stmmac_ethtool_ops = {
.begin = stmmac_check_if_running,
.get_drvinfo = stmmac_ethtool_getdrvinfo,
Expand All @@ -480,6 +535,8 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
.get_strings = stmmac_get_strings,
.get_wol = stmmac_get_wol,
.set_wol = stmmac_set_wol,
.get_eee = stmmac_ethtool_op_get_eee,
.set_eee = stmmac_ethtool_op_set_eee,
.get_sset_count = stmmac_get_sset_count,
.get_ts_info = ethtool_op_get_ts_info,
};
Expand Down
Loading

0 comments on commit bec1376

Please sign in to comment.