blob: cbefe9e2207cac01a418eb8df24fb8c82278c502 [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:
148 pr_debug("STMMAC: err in setting mulitcast filter\n");
149 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 }
216 }
217
218#ifdef FRAME_FILTER_DEBUG
219 /* Enable Receive all mode (to debug filtering_fail errors) */
220 value |= GMAC_FRAME_FILTER_RA;
221#endif
222 writel(value, ioaddr + GMAC_FRAME_FILTER);
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000223}
224
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500225
226static void dwmac1000_flow_ctrl(struct mac_device_info *hw, unsigned int duplex,
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000227 unsigned int fc, unsigned int pause_time)
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000228{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500229 void __iomem *ioaddr = hw->pcsr;
Vince Bridgers545d6552015-04-15 11:17:41 -0500230 /* Set flow such that DZPQ in Mac Register 6 is 0,
231 * and unicast pause detect is enabled.
232 */
233 unsigned int flow = GMAC_FLOW_CTRL_UP;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000234
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200235 pr_debug("GMAC Flow-Control:\n");
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000236 if (fc & FLOW_RX) {
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200237 pr_debug("\tReceive Flow-Control ON\n");
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000238 flow |= GMAC_FLOW_CTRL_RFE;
239 }
240 if (fc & FLOW_TX) {
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200241 pr_debug("\tTransmit Flow-Control ON\n");
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000242 flow |= GMAC_FLOW_CTRL_TFE;
243 }
244
245 if (duplex) {
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200246 pr_debug("\tduplex mode: PAUSE %d\n", pause_time);
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000247 flow |= (pause_time << GMAC_FLOW_CTRL_PT_SHIFT);
248 }
249
250 writel(flow, ioaddr + GMAC_FLOW_CTRL);
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000251}
252
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500253static void dwmac1000_pmt(struct mac_device_info *hw, unsigned long mode)
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000254{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500255 void __iomem *ioaddr = hw->pcsr;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000256 unsigned int pmt = 0;
257
Giuseppe Cavallaro74ae2fd2011-04-13 11:51:43 -0700258 if (mode & WAKE_MAGIC) {
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200259 pr_debug("GMAC: WOL Magic frame\n");
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000260 pmt |= power_down | magic_pkt_en;
Giuseppe Cavallaro74ae2fd2011-04-13 11:51:43 -0700261 }
262 if (mode & WAKE_UCAST) {
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200263 pr_debug("GMAC: WOL on global unicast\n");
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000264 pmt |= global_unicast;
265 }
266
267 writel(pmt, ioaddr + GMAC_PMT);
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000268}
269
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200270/* RGMII or SMII interface */
271static void dwmac1000_rgsmii(void __iomem *ioaddr, struct stmmac_extra_stats *x)
272{
273 u32 status;
274
275 status = readl(ioaddr + GMAC_RGSMIIIS);
276 x->irq_rgmii_n++;
277
278 /* Check the link status */
279 if (status & GMAC_RGSMIIIS_LNKSTS) {
280 int speed_value;
281
282 x->pcs_link = 1;
283
284 speed_value = ((status & GMAC_RGSMIIIS_SPEED) >>
285 GMAC_RGSMIIIS_SPEED_SHIFT);
286 if (speed_value == GMAC_RGSMIIIS_SPEED_125)
287 x->pcs_speed = SPEED_1000;
288 else if (speed_value == GMAC_RGSMIIIS_SPEED_25)
289 x->pcs_speed = SPEED_100;
290 else
291 x->pcs_speed = SPEED_10;
292
293 x->pcs_duplex = (status & GMAC_RGSMIIIS_LNKMOD_MASK);
294
295 pr_info("Link is Up - %d/%s\n", (int)x->pcs_speed,
296 x->pcs_duplex ? "Full" : "Half");
297 } else {
298 x->pcs_link = 0;
299 pr_info("Link is Down\n");
300 }
301}
302
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500303static int dwmac1000_irq_status(struct mac_device_info *hw,
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000304 struct stmmac_extra_stats *x)
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000305{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500306 void __iomem *ioaddr = hw->pcsr;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000307 u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000308 int ret = 0;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000309
310 /* Not used events (e.g. MMC interrupts) are not handled. */
Giuseppe CAVALLARO3fe5cad2016-06-24 15:16:25 +0200311 if ((intr_status & GMAC_INT_STATUS_MMCTIS))
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000312 x->mmc_tx_irq_n++;
Giuseppe CAVALLARO3fe5cad2016-06-24 15:16:25 +0200313 if (unlikely(intr_status & GMAC_INT_STATUS_MMCRIS))
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000314 x->mmc_rx_irq_n++;
Giuseppe CAVALLARO3fe5cad2016-06-24 15:16:25 +0200315 if (unlikely(intr_status & GMAC_INT_STATUS_MMCCSUM))
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000316 x->mmc_rx_csum_offload_irq_n++;
Giuseppe CAVALLARO3fe5cad2016-06-24 15:16:25 +0200317 if (unlikely(intr_status & GMAC_INT_DISABLE_PMT)) {
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000318 /* clear the PMT bits 5 and 6 by reading the PMT status reg */
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000319 readl(ioaddr + GMAC_PMT);
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000320 x->irq_receive_pmt_irq_n++;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000321 }
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200322
Giuseppe CAVALLARO3fe5cad2016-06-24 15:16:25 +0200323 /* MAC tx/rx EEE LPI entry/exit interrupts */
324 if (intr_status & GMAC_INT_STATUS_LPIIS) {
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000325 /* Clean LPI interrupt by reading the Reg 12 */
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000326 ret = readl(ioaddr + LPI_CTRL_STATUS);
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000327
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200328 if (ret & LPI_CTRL_STATUS_TLPIEN)
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000329 x->irq_tx_path_in_lpi_mode_n++;
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200330 if (ret & LPI_CTRL_STATUS_TLPIEX)
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000331 x->irq_tx_path_exit_lpi_mode_n++;
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200332 if (ret & LPI_CTRL_STATUS_RLPIEN)
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000333 x->irq_rx_path_in_lpi_mode_n++;
Giuseppe CAVALLARO83d7af62013-07-02 14:12:36 +0200334 if (ret & LPI_CTRL_STATUS_RLPIEX)
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000335 x->irq_rx_path_exit_lpi_mode_n++;
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000336 }
337
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200338 dwmac_pcs_isr(ioaddr, GMAC_PCS_BASE, intr_status, x);
Giuseppe CAVALLAROe58bb432013-03-26 04:43:08 +0000339
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200340 if (intr_status & PCS_RGSMIIIS_IRQ)
341 dwmac1000_rgsmii(ioaddr, x);
Giuseppe CAVALLARO0982a0f2013-03-26 04:43:07 +0000342
343 return ret;
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000344}
345
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500346static void dwmac1000_set_eee_mode(struct mac_device_info *hw)
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000347{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500348 void __iomem *ioaddr = hw->pcsr;
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000349 u32 value;
350
351 /* Enable the link status receive on RGMII, SGMII ore SMII
352 * receive path and instruct the transmit to enter in LPI
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000353 * state.
354 */
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000355 value = readl(ioaddr + LPI_CTRL_STATUS);
356 value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
357 writel(value, ioaddr + LPI_CTRL_STATUS);
358}
359
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500360static void dwmac1000_reset_eee_mode(struct mac_device_info *hw)
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000361{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500362 void __iomem *ioaddr = hw->pcsr;
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000363 u32 value;
364
365 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_set_eee_pls(struct mac_device_info *hw, int link)
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
377 if (link)
378 value |= LPI_CTRL_STATUS_PLS;
379 else
380 value &= ~LPI_CTRL_STATUS_PLS;
381
382 writel(value, ioaddr + LPI_CTRL_STATUS);
383}
384
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500385static void dwmac1000_set_eee_timer(struct mac_device_info *hw, int ls, int tw)
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000386{
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500387 void __iomem *ioaddr = hw->pcsr;
Giuseppe CAVALLAROd7659552012-06-27 21:14:37 +0000388 int value = ((tw & 0xffff)) | ((ls & 0x7ff) << 16);
389
390 /* Program the timers in the LPI timer control register:
391 * LS: minimum time (ms) for which the link
392 * status from PHY should be ok before transmitting
393 * the LPI pattern.
394 * TW: minimum time (us) for which the core waits
395 * after it has stopped transmitting the LPI pattern.
396 */
397 writel(value, ioaddr + LPI_TIMER_CTRL);
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000398}
399
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200400static void dwmac1000_ctrl_ane(void __iomem *ioaddr, bool ane, bool srgmi_ral,
401 bool loopback)
Giuseppe CAVALLAROe58bb432013-03-26 04:43:08 +0000402{
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200403 dwmac_ctrl_ane(ioaddr, GMAC_PCS_BASE, ane, srgmi_ral, loopback);
Giuseppe CAVALLAROe58bb432013-03-26 04:43:08 +0000404}
405
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200406static void dwmac1000_rane(void __iomem *ioaddr, bool restart)
Giuseppe CAVALLAROe58bb432013-03-26 04:43:08 +0000407{
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200408 dwmac_rane(ioaddr, GMAC_PCS_BASE, restart);
409}
Giuseppe CAVALLAROe58bb432013-03-26 04:43:08 +0000410
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200411static void dwmac1000_get_adv_lp(void __iomem *ioaddr, struct rgmii_adv *adv)
412{
413 dwmac_get_adv_lp(ioaddr, GMAC_PCS_BASE, adv);
Giuseppe CAVALLAROe58bb432013-03-26 04:43:08 +0000414}
415
Giuseppe CAVALLARO2f7a7912015-11-30 11:33:10 +0100416static void dwmac1000_debug(void __iomem *ioaddr, struct stmmac_extra_stats *x)
417{
418 u32 value = readl(ioaddr + GMAC_DEBUG);
419
420 if (value & GMAC_DEBUG_TXSTSFSTS)
421 x->mtl_tx_status_fifo_full++;
422 if (value & GMAC_DEBUG_TXFSTS)
423 x->mtl_tx_fifo_not_empty++;
424 if (value & GMAC_DEBUG_TWCSTS)
425 x->mmtl_fifo_ctrl++;
426 if (value & GMAC_DEBUG_TRCSTS_MASK) {
427 u32 trcsts = (value & GMAC_DEBUG_TRCSTS_MASK)
428 >> GMAC_DEBUG_TRCSTS_SHIFT;
429 if (trcsts == GMAC_DEBUG_TRCSTS_WRITE)
430 x->mtl_tx_fifo_read_ctrl_write++;
431 else if (trcsts == GMAC_DEBUG_TRCSTS_TXW)
432 x->mtl_tx_fifo_read_ctrl_wait++;
433 else if (trcsts == GMAC_DEBUG_TRCSTS_READ)
434 x->mtl_tx_fifo_read_ctrl_read++;
435 else
436 x->mtl_tx_fifo_read_ctrl_idle++;
437 }
438 if (value & GMAC_DEBUG_TXPAUSED)
439 x->mac_tx_in_pause++;
440 if (value & GMAC_DEBUG_TFCSTS_MASK) {
441 u32 tfcsts = (value & GMAC_DEBUG_TFCSTS_MASK)
442 >> GMAC_DEBUG_TFCSTS_SHIFT;
443
444 if (tfcsts == GMAC_DEBUG_TFCSTS_XFER)
445 x->mac_tx_frame_ctrl_xfer++;
446 else if (tfcsts == GMAC_DEBUG_TFCSTS_GEN_PAUSE)
447 x->mac_tx_frame_ctrl_pause++;
448 else if (tfcsts == GMAC_DEBUG_TFCSTS_WAIT)
449 x->mac_tx_frame_ctrl_wait++;
450 else
451 x->mac_tx_frame_ctrl_idle++;
452 }
453 if (value & GMAC_DEBUG_TPESTS)
454 x->mac_gmii_tx_proto_engine++;
455 if (value & GMAC_DEBUG_RXFSTS_MASK) {
456 u32 rxfsts = (value & GMAC_DEBUG_RXFSTS_MASK)
457 >> GMAC_DEBUG_RRCSTS_SHIFT;
458
459 if (rxfsts == GMAC_DEBUG_RXFSTS_FULL)
460 x->mtl_rx_fifo_fill_level_full++;
461 else if (rxfsts == GMAC_DEBUG_RXFSTS_AT)
462 x->mtl_rx_fifo_fill_above_thresh++;
463 else if (rxfsts == GMAC_DEBUG_RXFSTS_BT)
464 x->mtl_rx_fifo_fill_below_thresh++;
465 else
466 x->mtl_rx_fifo_fill_level_empty++;
467 }
468 if (value & GMAC_DEBUG_RRCSTS_MASK) {
469 u32 rrcsts = (value & GMAC_DEBUG_RRCSTS_MASK) >>
470 GMAC_DEBUG_RRCSTS_SHIFT;
471
472 if (rrcsts == GMAC_DEBUG_RRCSTS_FLUSH)
473 x->mtl_rx_fifo_read_ctrl_flush++;
474 else if (rrcsts == GMAC_DEBUG_RRCSTS_RSTAT)
475 x->mtl_rx_fifo_read_ctrl_read_data++;
476 else if (rrcsts == GMAC_DEBUG_RRCSTS_RDATA)
477 x->mtl_rx_fifo_read_ctrl_status++;
478 else
479 x->mtl_rx_fifo_read_ctrl_idle++;
480 }
481 if (value & GMAC_DEBUG_RWCSTS)
482 x->mtl_rx_fifo_ctrl_active++;
483 if (value & GMAC_DEBUG_RFCFCSTS_MASK)
484 x->mac_rx_frame_ctrl_fifo = (value & GMAC_DEBUG_RFCFCSTS_MASK)
485 >> GMAC_DEBUG_RFCFCSTS_SHIFT;
486 if (value & GMAC_DEBUG_RPESTS)
487 x->mac_gmii_rx_proto_engine++;
488}
489
stephen hemmingercadb7922010-10-13 14:51:25 +0000490static const struct stmmac_ops dwmac1000_ops = {
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000491 .core_init = dwmac1000_core_init,
Deepak SIKRI38912bd2012-04-04 04:33:21 +0000492 .rx_ipc = dwmac1000_rx_ipc_enable,
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000493 .dump_regs = dwmac1000_dump_regs,
494 .host_irq_status = dwmac1000_irq_status,
495 .set_filter = dwmac1000_set_filter,
496 .flow_ctrl = dwmac1000_flow_ctrl,
497 .pmt = dwmac1000_pmt,
498 .set_umac_addr = dwmac1000_set_umac_addr,
499 .get_umac_addr = dwmac1000_get_umac_addr,
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000500 .set_eee_mode = dwmac1000_set_eee_mode,
501 .reset_eee_mode = dwmac1000_reset_eee_mode,
502 .set_eee_timer = dwmac1000_set_eee_timer,
503 .set_eee_pls = dwmac1000_set_eee_pls,
Giuseppe CAVALLARO2f7a7912015-11-30 11:33:10 +0100504 .debug = dwmac1000_debug,
Giuseppe CAVALLARO70523e632016-06-24 15:16:24 +0200505 .pcs_ctrl_ane = dwmac1000_ctrl_ane,
506 .pcs_rane = dwmac1000_rane,
507 .pcs_get_adv_lp = dwmac1000_get_adv_lp,
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000508};
509
Vince Bridgers3b57de92014-07-31 15:49:17 -0500510struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins,
Alexandre TORGUEc623d142016-04-01 11:37:27 +0200511 int perfect_uc_entries,
512 int *synopsys_id)
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000513{
514 struct mac_device_info *mac;
Giuseppe CAVALLAROf0b9d782011-09-01 21:51:40 +0000515 u32 hwid = readl(ioaddr + GMAC_VERSION);
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000516
517 mac = kzalloc(sizeof(const struct mac_device_info), GFP_KERNEL);
Dan Carpenter1ff21902010-07-22 01:16:48 +0000518 if (!mac)
519 return NULL;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000520
Vince Bridgers7ed24bb2014-07-31 15:49:13 -0500521 mac->pcsr = ioaddr;
Vince Bridgers3b57de92014-07-31 15:49:17 -0500522 mac->multicast_filter_bins = mcbins;
523 mac->unicast_filter_entries = perfect_uc_entries;
524 mac->mcast_bits_log2 = 0;
525
526 if (mac->multicast_filter_bins)
527 mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
528
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000529 mac->mac = &dwmac1000_ops;
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000530 mac->dma = &dwmac1000_dma_ops;
531
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000532 mac->link.port = GMAC_CONTROL_PS;
533 mac->link.duplex = GMAC_CONTROL_DM;
534 mac->link.speed = GMAC_CONTROL_FES;
535 mac->mii.addr = GMAC_MII_ADDR;
536 mac->mii.data = GMAC_MII_DATA;
Alexandre TORGUEc623d142016-04-01 11:37:27 +0200537
538 /* Get and dump the chip ID */
539 *synopsys_id = stmmac_get_synopsys_id(hwid);
Giuseppe CAVALLARO21d437c2010-01-06 23:07:20 +0000540
541 return mac;
542}