lantiq: clarify VG3503J name
[oweals/openwrt.git] / target / linux / mvebu / patches-4.9 / 428-net-mvneta-add-EEE-support.patch
1 From: Russell King <rmk+kernel@arm.linux.org.uk>
2 Date: Tue, 29 Sep 2015 15:17:39 +0100
3 Subject: [PATCH] net: mvneta: add EEE support
4
5 Add EEE support to mvneta.  This allows us to enable the low power idle
6 support at MAC level if there is a PHY attached through phylink which
7 supports LPI.  The appropriate ethtool support is provided to allow the
8 feature to be controlled, including ethtool statistics for EEE wakeup
9 errors.
10
11 Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
12 ---
13
14 --- a/drivers/net/ethernet/marvell/mvneta.c
15 +++ b/drivers/net/ethernet/marvell/mvneta.c
16 @@ -243,6 +243,12 @@
17  #define MVNETA_TXQ_TOKEN_SIZE_REG(q)             (0x3e40 + ((q) << 2))
18  #define      MVNETA_TXQ_TOKEN_SIZE_MAX           0x7fffffff
19  
20 +#define MVNETA_LPI_CTRL_0                        0x2cc0
21 +#define MVNETA_LPI_CTRL_1                        0x2cc4
22 +#define      MVNETA_LPI_REQUEST_ENABLE           BIT(0)
23 +#define MVNETA_LPI_CTRL_2                        0x2cc8
24 +#define MVNETA_LPI_STATUS                        0x2ccc
25 +
26  #define MVNETA_CAUSE_TXQ_SENT_DESC_ALL_MASK     0xff
27  
28  /* Descriptor ring Macros */
29 @@ -316,6 +322,11 @@
30  #define MVNETA_RX_GET_BM_POOL_ID(rxd) \
31         (((rxd)->status & MVNETA_RXD_BM_POOL_MASK) >> MVNETA_RXD_BM_POOL_SHIFT)
32  
33 +enum {
34 +       ETHTOOL_STAT_EEE_WAKEUP,
35 +       ETHTOOL_MAX_STATS,
36 +};
37 +
38  struct mvneta_statistic {
39         unsigned short offset;
40         unsigned short type;
41 @@ -324,6 +335,7 @@ struct mvneta_statistic {
42  
43  #define T_REG_32       32
44  #define T_REG_64       64
45 +#define T_SW           1
46  
47  static const struct mvneta_statistic mvneta_statistics[] = {
48         { 0x3000, T_REG_64, "good_octets_received", },
49 @@ -358,6 +370,7 @@ static const struct mvneta_statistic mvn
50         { 0x304c, T_REG_32, "broadcast_frames_sent", },
51         { 0x3054, T_REG_32, "fc_sent", },
52         { 0x300c, T_REG_32, "internal_mac_transmit_err", },
53 +       { ETHTOOL_STAT_EEE_WAKEUP, T_SW, "eee_wakeup_errors", },
54  };
55  
56  struct mvneta_pcpu_stats {
57 @@ -416,6 +429,10 @@ struct mvneta_port {
58         struct mvneta_bm_pool *pool_short;
59         int bm_win_id;
60  
61 +       bool eee_enabled;
62 +       bool eee_active;
63 +       bool tx_lpi_enabled;
64 +
65         u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)];
66  
67         u32 indir[MVNETA_RSS_LU_TABLE_SIZE];
68 @@ -3291,6 +3308,18 @@ static void mvneta_mac_config(struct net
69                 mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, new_an);
70  }
71  
72 +static void mvneta_set_eee(struct mvneta_port *pp, bool enable)
73 +{
74 +       u32 lpi_ctl1;
75 +
76 +       lpi_ctl1 = mvreg_read(pp, MVNETA_LPI_CTRL_1);
77 +       if (enable)
78 +               lpi_ctl1 |= MVNETA_LPI_REQUEST_ENABLE;
79 +       else
80 +               lpi_ctl1 &= ~MVNETA_LPI_REQUEST_ENABLE;
81 +       mvreg_write(pp, MVNETA_LPI_CTRL_1, lpi_ctl1);
82 +}
83 +
84  static void mvneta_mac_link_down(struct net_device *ndev, unsigned int mode)
85  {
86         struct mvneta_port *pp = netdev_priv(ndev);
87 @@ -3304,6 +3333,9 @@ static void mvneta_mac_link_down(struct
88                 val |= MVNETA_GMAC_FORCE_LINK_DOWN;
89                 mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
90         }
91 +
92 +       pp->eee_active = false;
93 +       mvneta_set_eee(pp, false);
94  }
95  
96  static void mvneta_mac_link_up(struct net_device *ndev, unsigned int mode,
97 @@ -3320,6 +3352,11 @@ static void mvneta_mac_link_up(struct ne
98         }
99  
100         mvneta_port_up(pp);
101 +
102 +       if (phy && pp->eee_enabled) {
103 +               pp->eee_active = phy_init_eee(phy, 0) >= 0;
104 +               mvneta_set_eee(pp, pp->eee_active && pp->tx_lpi_enabled);
105 +       }
106  }
107  
108  static const struct phylink_mac_ops mvneta_phylink_ops = {
109 @@ -3772,6 +3809,13 @@ static void mvneta_ethtool_update_stats(
110                         high = readl_relaxed(base + s->offset + 4);
111                         val = (u64)high << 32 | low;
112                         break;
113 +               case T_SW:
114 +                       switch (s->offset) {
115 +                       case ETHTOOL_STAT_EEE_WAKEUP:
116 +                               val = phylink_get_eee_err(pp->phylink);
117 +                               break;
118 +                       }
119 +                       break;
120                 }
121  
122                 pp->ethtool_stats[i] += val;
123 @@ -3907,6 +3951,47 @@ static u16 mvneta_select_queue(struct ne
124  }
125  
126  
127 +static int mvneta_ethtool_get_eee(struct net_device *dev,
128 +                                 struct ethtool_eee *eee)
129 +{
130 +       struct mvneta_port *pp = netdev_priv(dev);
131 +       u32 lpi_ctl0;
132 +
133 +       lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0);
134 +
135 +       eee->eee_enabled = pp->eee_enabled;
136 +       eee->eee_active = pp->eee_active;
137 +       eee->tx_lpi_enabled = pp->tx_lpi_enabled;
138 +       eee->tx_lpi_timer = (lpi_ctl0) >> 8; // * scale;
139 +
140 +       return phylink_ethtool_get_eee(pp->phylink, eee);
141 +}
142 +
143 +static int mvneta_ethtool_set_eee(struct net_device *dev,
144 +                                 struct ethtool_eee *eee)
145 +{
146 +       struct mvneta_port *pp = netdev_priv(dev);
147 +       u32 lpi_ctl0;
148 +
149 +       /* The Armada 37x documents do not give limits for this other than
150 +        * it being an 8-bit register. */
151 +       if (eee->tx_lpi_enabled &&
152 +           (eee->tx_lpi_timer < 0 || eee->tx_lpi_timer > 255))
153 +               return -EINVAL;
154 +
155 +       lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0);
156 +       lpi_ctl0 &= ~(0xff << 8);
157 +       lpi_ctl0 |= eee->tx_lpi_timer << 8;
158 +       mvreg_write(pp, MVNETA_LPI_CTRL_0, lpi_ctl0);
159 +
160 +       pp->eee_enabled = eee->eee_enabled;
161 +       pp->tx_lpi_enabled = eee->tx_lpi_enabled;
162 +
163 +       mvneta_set_eee(pp, eee->tx_lpi_enabled && eee->eee_enabled);
164 +
165 +       return phylink_ethtool_set_eee(pp->phylink, eee);
166 +}
167 +
168  static const struct net_device_ops mvneta_netdev_ops = {
169         .ndo_open            = mvneta_open,
170         .ndo_stop            = mvneta_stop,
171 @@ -3939,6 +4024,8 @@ const struct ethtool_ops mvneta_eth_tool
172         .set_rxfh       = mvneta_ethtool_set_rxfh,
173         .get_link_ksettings = mvneta_ethtool_get_link_ksettings,
174         .set_link_ksettings = mvneta_ethtool_set_link_ksettings,
175 +       .get_eee        = mvneta_ethtool_get_eee,
176 +       .set_eee        = mvneta_ethtool_set_eee,
177  };
178  
179  /* Initialize hw */