blob: 093e58e94075ae44fd474245df440dd0d88f6150 [file] [log] [blame]
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +00001/*******************************************************************************
2 This is the driver for the GMAC on-chip Ethernet controller for ST SoCs.
3 DWC Ether MAC 10/100/1000 Universal version 3.41a has been used for
4 developing this code.
5
6 This only implements the mac core functions for this chip.
7
8 Copyright (C) 2007-2009 STMicroelectronics Ltd
9
10 This program is free software; you can redistribute it and/or modify it
11 under the terms and conditions of the GNU General Public License,
12 version 2, as published by the Free Software Foundation.
13
14 This program is distributed in the hope it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 more details.
18
19 You should have received a copy of the GNU General Public License along with
20 this program; if not, write to the Free Software Foundation, Inc.,
21 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
22
23 The full GNU General Public License is included in this distribution in
24 the file called "COPYING".
25
26 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
27*******************************************************************************/
28
29#include <linux/crc32.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090030#include <linux/slab.h>
Giuseppe CAVALLAROe58bb432013-03-26 04:43:08 +000031#include <linux/ethtool.h>
Alexey Dobriyanb7f080c2011-06-16 11:01:34 +000032#include <asm/io.h>
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +020033#include "stmmac_pcs.h"
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +000034#include "dwmac1000.h"
35
Vince Bridgers7ed24bb2014-07-31 15:49:13 -050036static void dwmac1000_core_init(struct mac_device_info *hw, int mtu)
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +000037{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -050038 void __iomem *ioaddr = hw->pcsr;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +000039 u32 value = readl(ioaddr + GMAC_CONTROL);
Giuseppe CAVALLARO3fe5cad2016-06-24 15:16:25 +020040
41 /* Configure GMAC core */
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +000042 value |= GMAC_CORE_INIT;
Giuseppe CAVALLARO3fe5cad2016-06-24 15:16:25 +020043
Vince Bridgers2618abb2014-01-20 05:39:01 -060044 if (mtu > 1500)
45 value |= GMAC_CONTROL_2K;
46 if (mtu > 2000)
47 value |= GMAC_CONTROL_JE;
48
Giuseppe CAVALLARO02e57b92016-06-24 15:16:26 +020049 if (hw->ps) {
50 value |= GMAC_CONTROL_TE;
51
52 if (hw->ps == SPEED_1000) {
53 value &= ~GMAC_CONTROL_PS;
54 } else {
55 value |= GMAC_CONTROL_PS;
56
57 if (hw->ps == SPEED_10)
58 value &= ~GMAC_CONTROL_FES;
59 else
60 value |= GMAC_CONTROL_FES;
61 }
62 }
63
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +000064 writel(value, ioaddr + GMAC_CONTROL);
65
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +000066 /* Mask GMAC interrupts */
Giuseppe CAVALLARO3fe5cad2016-06-24 15:16:25 +020067 value = GMAC_INT_DEFAULT_MASK;
68
69 if (hw->pmt)
70 value &= ~GMAC_INT_DISABLE_PMT;
71 if (hw->pcs)
72 value &= ~GMAC_INT_DISABLE_PCS;
73
74 writel(value, ioaddr + GMAC_INT_MASK);
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +000075
76#ifdef STMMAC_VLAN_TAG_USED
77 /* Tag detection without filtering */
78 writel(0x0, ioaddr + GMAC_VLAN_TAG);
79#endif
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +000080}
81
Vince Bridgers7ed24bb2014-07-31 15:49:13 -050082static int dwmac1000_rx_ipc_enable(struct mac_device_info *hw)
Giuseppe CAVALLAROebbb2932010-09-17 03:23:40 +000083{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -050084 void __iomem *ioaddr = hw->pcsr;
Giuseppe CAVALLAROebbb2932010-09-17 03:23:40 +000085 u32 value = readl(ioaddr + GMAC_CONTROL);
86
Giuseppe CAVALLAROd2afb5b2014-09-01 09:17:52 +020087 if (hw->rx_csum)
88 value |= GMAC_CONTROL_IPC;
89 else
90 value &= ~GMAC_CONTROL_IPC;
91
Giuseppe CAVALLAROebbb2932010-09-17 03:23:40 +000092 writel(value, ioaddr + GMAC_CONTROL);
93
94 value = readl(ioaddr + GMAC_CONTROL);
95
96 return !!(value & GMAC_CONTROL_IPC);
97}
98
Vince Bridgers7ed24bb2014-07-31 15:49:13 -050099static void dwmac1000_dump_regs(struct mac_device_info *hw)
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000100{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500101 void __iomem *ioaddr = hw->pcsr;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000102 int i;
David S. Miller1f0f6382010-08-30 21:55:17 -0700103 pr_info("\tDWMAC1000 regs (base addr = 0x%p)\n", ioaddr);
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000104
105 for (i = 0; i < 55; i++) {
106 int offset = i * 4;
107 pr_info("\tReg No. %d (offset 0x%x): 0x%08x\n", i,
108 offset, readl(ioaddr + offset));
109 }
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000110}
111
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500112static void dwmac1000_set_umac_addr(struct mac_device_info *hw,
113 unsigned char *addr,
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000114 unsigned int reg_n)
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000115{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500116 void __iomem *ioaddr = hw->pcsr;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000117 stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000118 GMAC_ADDR_LOW(reg_n));
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000119}
120
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500121static void dwmac1000_get_umac_addr(struct mac_device_info *hw,
122 unsigned char *addr,
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000123 unsigned int reg_n)
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000124{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500125 void __iomem *ioaddr = hw->pcsr;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000126 stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000127 GMAC_ADDR_LOW(reg_n));
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000128}
129
Vince Bridgers3b57de92014-07-31 15:49:17 -0500130static void dwmac1000_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits,
131 int mcbitslog2)
132{
133 int numhashregs, regs;
134
135 switch (mcbitslog2) {
136 case 6:
137 writel(mcfilterbits[0], ioaddr + GMAC_HASH_LOW);
138 writel(mcfilterbits[1], ioaddr + GMAC_HASH_HIGH);
139 return;
140 break;
141 case 7:
142 numhashregs = 4;
143 break;
144 case 8:
145 numhashregs = 8;
146 break;
147 default:
Colin Ian Kingcf4d13f2016-08-26 19:35:25 +0100148 pr_debug("STMMAC: err in setting multicast filter\n");
Vince Bridgers3b57de92014-07-31 15:49:17 -0500149 return;
150 break;
151 }
152 for (regs = 0; regs < numhashregs; regs++)
153 writel(mcfilterbits[regs],
154 ioaddr + GMAC_EXTHASH_BASE + regs * 4);
155}
156
157static void dwmac1000_set_filter(struct mac_device_info *hw,
158 struct net_device *dev)
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000159{
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000160 void __iomem *ioaddr = (void __iomem *)dev->base_addr;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000161 unsigned int value = 0;
Vince Bridgers3b57de92014-07-31 15:49:17 -0500162 unsigned int perfect_addr_number = hw->unicast_filter_entries;
Vince Bridgers3dab99e2014-10-09 10:10:36 -0500163 u32 mc_filter[8];
Vince Bridgers3b57de92014-07-31 15:49:17 -0500164 int mcbitslog2 = hw->mcast_bits_log2;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000165
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200166 pr_debug("%s: # mcasts %d, # unicast %d\n", __func__,
167 netdev_mc_count(dev), netdev_uc_count(dev));
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000168
Vince Bridgersaefef4c2014-07-31 15:49:14 -0500169 memset(mc_filter, 0, sizeof(mc_filter));
170
171 if (dev->flags & IFF_PROMISC) {
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000172 value = GMAC_FRAME_FILTER_PR;
Vince Bridgersaefef4c2014-07-31 15:49:14 -0500173 } else if (dev->flags & IFF_ALLMULTI) {
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000174 value = GMAC_FRAME_FILTER_PM; /* pass all multi */
Jiri Pirko4cd24ea2010-02-08 04:30:35 +0000175 } else if (!netdev_mc_empty(dev)) {
Jiri Pirko22bedad32010-04-01 21:22:57 +0000176 struct netdev_hw_addr *ha;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000177
178 /* Hash filter for multicast */
179 value = GMAC_FRAME_FILTER_HMC;
180
Jiri Pirko22bedad32010-04-01 21:22:57 +0000181 netdev_for_each_mc_addr(ha, dev) {
Vince Bridgers3b57de92014-07-31 15:49:17 -0500182 /* The upper n bits of the calculated CRC are used to
183 * index the contents of the hash table. The number of
184 * bits used depends on the hardware configuration
185 * selected at core configuration time.
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000186 */
Vince Bridgers3b57de92014-07-31 15:49:17 -0500187 int bit_nr = bitrev32(~crc32_le(~0, ha->addr,
188 ETH_ALEN)) >>
189 (32 - mcbitslog2);
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000190 /* The most significant bit determines the register to
191 * use (H/L) while the other 5 bits determine the bit
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000192 * within the register.
193 */
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000194 mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
195 }
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000196 }
197
Vince Bridgers3b57de92014-07-31 15:49:17 -0500198 dwmac1000_set_mchash(ioaddr, mc_filter, mcbitslog2);
Giuseppe CAVALLAROcffb13f2012-05-13 22:18:41 +0000199
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000200 /* Handle multiple unicast addresses (perfect filtering) */
Giuseppe CAVALLAROcffb13f2012-05-13 22:18:41 +0000201 if (netdev_uc_count(dev) > perfect_addr_number)
Vince Bridgers3b57de92014-07-31 15:49:17 -0500202 /* Switch to promiscuous mode if more than unicast
203 * addresses are requested than supported by hardware.
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000204 */
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000205 value |= GMAC_FRAME_FILTER_PR;
206 else {
207 int reg = 1;
208 struct netdev_hw_addr *ha;
209
Jiri Pirko32e7bfc2010-01-25 13:36:10 -0800210 netdev_for_each_uc_addr(ha, dev) {
Vince Bridgers3dab99e2014-10-09 10:10:36 -0500211 stmmac_set_mac_addr(ioaddr, ha->addr,
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500212 GMAC_ADDR_HIGH(reg),
213 GMAC_ADDR_LOW(reg));
Jiri Pirko32e7bfc2010-01-25 13:36:10 -0800214 reg++;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000215 }
Jose Abreuc66c5da2019-05-24 10:20:21 +0200216
217 while (reg <= perfect_addr_number) {
218 writel(0, ioaddr + GMAC_ADDR_HIGH(reg));
219 writel(0, ioaddr + GMAC_ADDR_LOW(reg));
220 reg++;
221 }
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000222 }
223
224#ifdef FRAME_FILTER_DEBUG
225 /* Enable Receive all mode (to debug filtering_fail errors) */
226 value |= GMAC_FRAME_FILTER_RA;
227#endif
228 writel(value, ioaddr + GMAC_FRAME_FILTER);
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000229}
230
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500231
232static void dwmac1000_flow_ctrl(struct mac_device_info *hw, unsigned int duplex,
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000233 unsigned int fc, unsigned int pause_time)
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000234{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500235 void __iomem *ioaddr = hw->pcsr;
Vince Bridgers545d6552015-04-15 11:17:41 -0500236 /* Set flow such that DZPQ in Mac Register 6 is 0,
237 * and unicast pause detect is enabled.
238 */
239 unsigned int flow = GMAC_FLOW_CTRL_UP;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000240
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200241 pr_debug("GMAC Flow-Control:\n");
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000242 if (fc & FLOW_RX) {
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200243 pr_debug("\tReceive Flow-Control ON\n");
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000244 flow |= GMAC_FLOW_CTRL_RFE;
245 }
246 if (fc & FLOW_TX) {
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200247 pr_debug("\tTransmit Flow-Control ON\n");
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000248 flow |= GMAC_FLOW_CTRL_TFE;
249 }
250
251 if (duplex) {
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200252 pr_debug("\tduplex mode: PAUSE %d\n", pause_time);
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000253 flow |= (pause_time << GMAC_FLOW_CTRL_PT_SHIFT);
254 }
255
256 writel(flow, ioaddr + GMAC_FLOW_CTRL);
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000257}
258
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500259static void dwmac1000_pmt(struct mac_device_info *hw, unsigned long mode)
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000260{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500261 void __iomem *ioaddr = hw->pcsr;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000262 unsigned int pmt = 0;
263
Giuseppe Cavallaro74ae2fd2011-04-13 11:51:43 -0700264 if (mode & WAKE_MAGIC) {
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200265 pr_debug("GMAC: WOL Magic frame\n");
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000266 pmt |= power_down | magic_pkt_en;
Giuseppe Cavallaro74ae2fd2011-04-13 11:51:43 -0700267 }
268 if (mode & WAKE_UCAST) {
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200269 pr_debug("GMAC: WOL on global unicast\n");
Giuseppe CAVALLARO19cd1202016-09-16 10:50:13 +0200270 pmt |= power_down | global_unicast | wake_up_frame_en;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000271 }
272
273 writel(pmt, ioaddr + GMAC_PMT);
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000274}
275
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200276/* RGMII or SMII interface */
277static void dwmac1000_rgsmii(void __iomem *ioaddr, struct stmmac_extra_stats *x)
278{
279 u32 status;
280
281 status = readl(ioaddr + GMAC_RGSMIIIS);
282 x->irq_rgmii_n++;
283
284 /* Check the link status */
285 if (status & GMAC_RGSMIIIS_LNKSTS) {
286 int speed_value;
287
288 x->pcs_link = 1;
289
290 speed_value = ((status & GMAC_RGSMIIIS_SPEED) >>
291 GMAC_RGSMIIIS_SPEED_SHIFT);
292 if (speed_value == GMAC_RGSMIIIS_SPEED_125)
293 x->pcs_speed = SPEED_1000;
294 else if (speed_value == GMAC_RGSMIIIS_SPEED_25)
295 x->pcs_speed = SPEED_100;
296 else
297 x->pcs_speed = SPEED_10;
298
299 x->pcs_duplex = (status & GMAC_RGSMIIIS_LNKMOD_MASK);
300
301 pr_info("Link is Up - %d/%s\n", (int)x->pcs_speed,
302 x->pcs_duplex ? "Full" : "Half");
303 } else {
304 x->pcs_link = 0;
305 pr_info("Link is Down\n");
306 }
307}
308
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500309static int dwmac1000_irq_status(struct mac_device_info *hw,
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000310 struct stmmac_extra_stats *x)
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000311{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500312 void __iomem *ioaddr = hw->pcsr;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000313 u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
Alexey Brodkin455a4572017-01-27 15:24:43 +0300314 u32 intr_mask = readl(ioaddr + GMAC_INT_MASK);
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000315 int ret = 0;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000316
Alexey Brodkin455a4572017-01-27 15:24:43 +0300317 /* Discard masked bits */
318 intr_status &= ~intr_mask;
319
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000320 /* Not used events (e.g. MMC interrupts) are not handled. */
Giuseppe CAVALLARO3fe5cad2016-06-24 15:16:25 +0200321 if ((intr_status & GMAC_INT_STATUS_MMCTIS))
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000322 x->mmc_tx_irq_n++;
Giuseppe CAVALLARO3fe5cad2016-06-24 15:16:25 +0200323 if (unlikely(intr_status & GMAC_INT_STATUS_MMCRIS))
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000324 x->mmc_rx_irq_n++;
Giuseppe CAVALLARO3fe5cad2016-06-24 15:16:25 +0200325 if (unlikely(intr_status & GMAC_INT_STATUS_MMCCSUM))
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000326 x->mmc_rx_csum_offload_irq_n++;
Giuseppe CAVALLARO3fe5cad2016-06-24 15:16:25 +0200327 if (unlikely(intr_status & GMAC_INT_DISABLE_PMT)) {
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000328 /* clear the PMT bits 5 and 6 by reading the PMT status reg */
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000329 readl(ioaddr + GMAC_PMT);
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000330 x->irq_receive_pmt_irq_n++;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000331 }
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200332
Giuseppe CAVALLARO3fe5cad2016-06-24 15:16:25 +0200333 /* MAC tx/rx EEE LPI entry/exit interrupts */
334 if (intr_status & GMAC_INT_STATUS_LPIIS) {
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000335 /* Clean LPI interrupt by reading the Reg 12 */
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000336 ret = readl(ioaddr + LPI_CTRL_STATUS);
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000337
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200338 if (ret & LPI_CTRL_STATUS_TLPIEN)
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000339 x->irq_tx_path_in_lpi_mode_n++;
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200340 if (ret & LPI_CTRL_STATUS_TLPIEX)
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000341 x->irq_tx_path_exit_lpi_mode_n++;
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200342 if (ret & LPI_CTRL_STATUS_RLPIEN)
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000343 x->irq_rx_path_in_lpi_mode_n++;
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200344 if (ret & LPI_CTRL_STATUS_RLPIEX)
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000345 x->irq_rx_path_exit_lpi_mode_n++;
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000346 }
347
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200348 dwmac_pcs_isr(ioaddr, GMAC_PCS_BASE, intr_status, x);
Giuseppe CAVALLAROe58bb432013-03-26 04:43:08 +0000349
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200350 if (intr_status & PCS_RGSMIIIS_IRQ)
351 dwmac1000_rgsmii(ioaddr, x);
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000352
353 return ret;
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000354}
355
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500356static void dwmac1000_set_eee_mode(struct mac_device_info *hw)
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000357{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500358 void __iomem *ioaddr = hw->pcsr;
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000359 u32 value;
360
361 /* Enable the link status receive on RGMII, SGMII ore SMII
362 * receive path and instruct the transmit to enter in LPI
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000363 * state.
364 */
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000365 value = readl(ioaddr + LPI_CTRL_STATUS);
366 value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
367 writel(value, ioaddr + LPI_CTRL_STATUS);
368}
369
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500370static void dwmac1000_reset_eee_mode(struct mac_device_info *hw)
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000371{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500372 void __iomem *ioaddr = hw->pcsr;
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000373 u32 value;
374
375 value = readl(ioaddr + LPI_CTRL_STATUS);
376 value &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA);
377 writel(value, ioaddr + LPI_CTRL_STATUS);
378}
379
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500380static void dwmac1000_set_eee_pls(struct mac_device_info *hw, int link)
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000381{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500382 void __iomem *ioaddr = hw->pcsr;
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000383 u32 value;
384
385 value = readl(ioaddr + LPI_CTRL_STATUS);
386
387 if (link)
388 value |= LPI_CTRL_STATUS_PLS;
389 else
390 value &= ~LPI_CTRL_STATUS_PLS;
391
392 writel(value, ioaddr + LPI_CTRL_STATUS);
393}
394
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500395static void dwmac1000_set_eee_timer(struct mac_device_info *hw, int ls, int tw)
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000396{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500397 void __iomem *ioaddr = hw->pcsr;
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000398 int value = ((tw & 0xffff)) | ((ls & 0x7ff) << 16);
399
400 /* Program the timers in the LPI timer control register:
401 * LS: minimum time (ms) for which the link
402 * status from PHY should be ok before transmitting
403 * the LPI pattern.
404 * TW: minimum time (us) for which the core waits
405 * after it has stopped transmitting the LPI pattern.
406 */
407 writel(value, ioaddr + LPI_TIMER_CTRL);
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000408}
409
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200410static void dwmac1000_ctrl_ane(void __iomem *ioaddr, bool ane, bool srgmi_ral,
411 bool loopback)
Giuseppe CAVALLAROe58bb432013-03-26 04:43:08 +0000412{
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200413 dwmac_ctrl_ane(ioaddr, GMAC_PCS_BASE, ane, srgmi_ral, loopback);
Giuseppe CAVALLAROe58bb432013-03-26 04:43:08 +0000414}
415
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200416static void dwmac1000_rane(void __iomem *ioaddr, bool restart)
Giuseppe CAVALLAROe58bb432013-03-26 04:43:08 +0000417{
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200418 dwmac_rane(ioaddr, GMAC_PCS_BASE, restart);
419}
Giuseppe CAVALLAROe58bb432013-03-26 04:43:08 +0000420
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200421static void dwmac1000_get_adv_lp(void __iomem *ioaddr, struct rgmii_adv *adv)
422{
423 dwmac_get_adv_lp(ioaddr, GMAC_PCS_BASE, adv);
Giuseppe CAVALLAROe58bb432013-03-26 04:43:08 +0000424}
425
Giuseppe CAVALLARO2f7a7912015-11-30 11:33:10 +0100426static void dwmac1000_debug(void __iomem *ioaddr, struct stmmac_extra_stats *x)
427{
428 u32 value = readl(ioaddr + GMAC_DEBUG);
429
430 if (value & GMAC_DEBUG_TXSTSFSTS)
431 x->mtl_tx_status_fifo_full++;
432 if (value & GMAC_DEBUG_TXFSTS)
433 x->mtl_tx_fifo_not_empty++;
434 if (value & GMAC_DEBUG_TWCSTS)
435 x->mmtl_fifo_ctrl++;
436 if (value & GMAC_DEBUG_TRCSTS_MASK) {
437 u32 trcsts = (value & GMAC_DEBUG_TRCSTS_MASK)
438 >> GMAC_DEBUG_TRCSTS_SHIFT;
439 if (trcsts == GMAC_DEBUG_TRCSTS_WRITE)
440 x->mtl_tx_fifo_read_ctrl_write++;
441 else if (trcsts == GMAC_DEBUG_TRCSTS_TXW)
442 x->mtl_tx_fifo_read_ctrl_wait++;
443 else if (trcsts == GMAC_DEBUG_TRCSTS_READ)
444 x->mtl_tx_fifo_read_ctrl_read++;
445 else
446 x->mtl_tx_fifo_read_ctrl_idle++;
447 }
448 if (value & GMAC_DEBUG_TXPAUSED)
449 x->mac_tx_in_pause++;
450 if (value & GMAC_DEBUG_TFCSTS_MASK) {
451 u32 tfcsts = (value & GMAC_DEBUG_TFCSTS_MASK)
452 >> GMAC_DEBUG_TFCSTS_SHIFT;
453
454 if (tfcsts == GMAC_DEBUG_TFCSTS_XFER)
455 x->mac_tx_frame_ctrl_xfer++;
456 else if (tfcsts == GMAC_DEBUG_TFCSTS_GEN_PAUSE)
457 x->mac_tx_frame_ctrl_pause++;
458 else if (tfcsts == GMAC_DEBUG_TFCSTS_WAIT)
459 x->mac_tx_frame_ctrl_wait++;
460 else
461 x->mac_tx_frame_ctrl_idle++;
462 }
463 if (value & GMAC_DEBUG_TPESTS)
464 x->mac_gmii_tx_proto_engine++;
465 if (value & GMAC_DEBUG_RXFSTS_MASK) {
466 u32 rxfsts = (value & GMAC_DEBUG_RXFSTS_MASK)
467 >> GMAC_DEBUG_RRCSTS_SHIFT;
468
469 if (rxfsts == GMAC_DEBUG_RXFSTS_FULL)
470 x->mtl_rx_fifo_fill_level_full++;
471 else if (rxfsts == GMAC_DEBUG_RXFSTS_AT)
472 x->mtl_rx_fifo_fill_above_thresh++;
473 else if (rxfsts == GMAC_DEBUG_RXFSTS_BT)
474 x->mtl_rx_fifo_fill_below_thresh++;
475 else
476 x->mtl_rx_fifo_fill_level_empty++;
477 }
478 if (value & GMAC_DEBUG_RRCSTS_MASK) {
479 u32 rrcsts = (value & GMAC_DEBUG_RRCSTS_MASK) >>
480 GMAC_DEBUG_RRCSTS_SHIFT;
481
482 if (rrcsts == GMAC_DEBUG_RRCSTS_FLUSH)
483 x->mtl_rx_fifo_read_ctrl_flush++;
484 else if (rrcsts == GMAC_DEBUG_RRCSTS_RSTAT)
485 x->mtl_rx_fifo_read_ctrl_read_data++;
486 else if (rrcsts == GMAC_DEBUG_RRCSTS_RDATA)
487 x->mtl_rx_fifo_read_ctrl_status++;
488 else
489 x->mtl_rx_fifo_read_ctrl_idle++;
490 }
491 if (value & GMAC_DEBUG_RWCSTS)
492 x->mtl_rx_fifo_ctrl_active++;
493 if (value & GMAC_DEBUG_RFCFCSTS_MASK)
494 x->mac_rx_frame_ctrl_fifo = (value & GMAC_DEBUG_RFCFCSTS_MASK)
495 >> GMAC_DEBUG_RFCFCSTS_SHIFT;
496 if (value & GMAC_DEBUG_RPESTS)
497 x->mac_gmii_rx_proto_engine++;
498}
499
stephen hemmingercadb7922010-10-13 14:51:25 +0000500static const struct stmmac_ops dwmac1000_ops = {
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000501 .core_init = dwmac1000_core_init,
Deepak SIKRI38912bd2012-04-04 04:33:21 +0000502 .rx_ipc = dwmac1000_rx_ipc_enable,
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000503 .dump_regs = dwmac1000_dump_regs,
504 .host_irq_status = dwmac1000_irq_status,
505 .set_filter = dwmac1000_set_filter,
506 .flow_ctrl = dwmac1000_flow_ctrl,
507 .pmt = dwmac1000_pmt,
508 .set_umac_addr = dwmac1000_set_umac_addr,
509 .get_umac_addr = dwmac1000_get_umac_addr,
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000510 .set_eee_mode = dwmac1000_set_eee_mode,
511 .reset_eee_mode = dwmac1000_reset_eee_mode,
512 .set_eee_timer = dwmac1000_set_eee_timer,
513 .set_eee_pls = dwmac1000_set_eee_pls,
Giuseppe CAVALLARO2f7a7912015-11-30 11:33:10 +0100514 .debug = dwmac1000_debug,
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200515 .pcs_ctrl_ane = dwmac1000_ctrl_ane,
516 .pcs_rane = dwmac1000_rane,
517 .pcs_get_adv_lp = dwmac1000_get_adv_lp,
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000518};
519
Vince Bridgers3b57de92014-07-31 15:49:17 -0500520struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins,
Alexandre TORGUEc623d142016-04-01 11:37:27 +0200521 int perfect_uc_entries,
522 int *synopsys_id)
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000523{
524 struct mac_device_info *mac;
Giuseppe CAVALLAROf0b9d782011-09-01 21:51:40 +0000525 u32 hwid = readl(ioaddr + GMAC_VERSION);
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000526
527 mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL);
Dan Carpenter1ff21902010-07-22 01:16:48 +0000528 if (!mac)
529 return NULL;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000530
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500531 mac->pcsr = ioaddr;
Vince Bridgers3b57de92014-07-31 15:49:17 -0500532 mac->multicast_filter_bins = mcbins;
533 mac->unicast_filter_entries = perfect_uc_entries;
534 mac->mcast_bits_log2 = 0;
535
536 if (mac->multicast_filter_bins)
537 mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
538
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000539 mac->mac = &dwmac1000_ops;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000540 mac->dma = &dwmac1000_dma_ops;
541
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000542 mac->link.port = GMAC_CONTROL_PS;
543 mac->link.duplex = GMAC_CONTROL_DM;
544 mac->link.speed = GMAC_CONTROL_FES;
545 mac->mii.addr = GMAC_MII_ADDR;
546 mac->mii.data = GMAC_MII_DATA;
Alexandre TORGUEc623d142016-04-01 11:37:27 +0200547
548 /* Get and dump the chip ID */
549 *synopsys_id = stmmac_get_synopsys_id(hwid);
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000550
551 return mac;
552}