1 /*
2  * This file is based on code from OCTEON SDK by Cavium Networks.
3  *
4  * Copyright (c) 2003-2007 Cavium Networks
5  *
6  * This file is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License, Version 2, as
8  * published by the Free Software Foundation.
9  */
10 
11 #include <linux/kernel.h>
12 #include <linux/netdevice.h>
13 #include <linux/interrupt.h>
14 #include <linux/phy.h>
15 #include <linux/ratelimit.h>
16 #include <net/dst.h>
17 
18 #include <asm/octeon/octeon.h>
19 
20 #include "ethernet-defines.h"
21 #include "octeon-ethernet.h"
22 #include "ethernet-util.h"
23 #include "ethernet-mdio.h"
24 
25 #include <asm/octeon/cvmx-helper.h>
26 
27 #include <asm/octeon/cvmx-ipd-defs.h>
28 #include <asm/octeon/cvmx-npi-defs.h>
29 #include <asm/octeon/cvmx-gmxx-defs.h>
30 
31 static DEFINE_SPINLOCK(global_register_lock);
32 
33 static int number_rgmii_ports;
34 
35 static void cvm_oct_set_hw_preamble(struct octeon_ethernet *priv, bool enable)
36 {
37 	union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
38 	union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
39 	union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
40 	int interface = INTERFACE(priv->port);
41 	int index = INDEX(priv->port);
42 
43 	/* Set preamble checking. */
44 	gmxx_rxx_frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index,
45 								   interface));
46 	gmxx_rxx_frm_ctl.s.pre_chk = enable;
47 	cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface),
48 		       gmxx_rxx_frm_ctl.u64);
49 
50 	/* Set FCS stripping. */
51 	ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
52 	if (enable)
53 		ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port;
54 	else
55 		ipd_sub_port_fcs.s.port_bit &=
56 					0xffffffffull ^ (1ull << priv->port);
57 	cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64);
58 
59 	/* Clear any error bits. */
60 	gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index,
61 								   interface));
62 	cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
63 		       gmxx_rxx_int_reg.u64);
64 }
65 
66 static void cvm_oct_rgmii_poll(struct net_device *dev)
67 {
68 	struct octeon_ethernet *priv = netdev_priv(dev);
69 	unsigned long flags = 0;
70 	cvmx_helper_link_info_t link_info;
71 	int use_global_register_lock = (priv->phydev == NULL);
72 
73 	BUG_ON(in_interrupt());
74 	if (use_global_register_lock) {
75 		/*
76 		 * Take the global register lock since we are going to
77 		 * touch registers that affect more than one port.
78 		 */
79 		spin_lock_irqsave(&global_register_lock, flags);
80 	} else {
81 		mutex_lock(&priv->phydev->bus->mdio_lock);
82 	}
83 
84 	link_info = cvmx_helper_link_get(priv->port);
85 	if (link_info.u64 == priv->link_info) {
86 		if (link_info.s.speed == 10) {
87 			/*
88 			 * Read the GMXX_RXX_INT_REG[PCTERR] bit and
89 			 * see if we are getting preamble errors.
90 			 */
91 			int interface = INTERFACE(priv->port);
92 			int index = INDEX(priv->port);
93 			union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
94 
95 			gmxx_rxx_int_reg.u64 =
96 			    cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
97 					  (index, interface));
98 			if (gmxx_rxx_int_reg.s.pcterr) {
99 				/*
100 				 * We are getting preamble errors at
101 				 * 10Mbps.  Most likely the PHY is
102 				 * giving us packets with mis aligned
103 				 * preambles. In order to get these
104 				 * packets we need to disable preamble
105 				 * checking and do it in software.
106 				 */
107 				cvm_oct_set_hw_preamble(priv, false);
108 				printk_ratelimited("%s: Using 10Mbps with software preamble removal\n",
109 						   dev->name);
110 			}
111 		}
112 
113 		if (use_global_register_lock)
114 			spin_unlock_irqrestore(&global_register_lock, flags);
115 		else
116 			mutex_unlock(&priv->phydev->bus->mdio_lock);
117 		return;
118 	}
119 
120 	/* Since the 10Mbps preamble workaround is allowed we need to enable
121 	 * preamble checking, FCS stripping, and clear error bits on
122 	 * every speed change. If errors occur during 10Mbps operation
123 	 * the above code will change this stuff
124 	 */
125 	cvm_oct_set_hw_preamble(priv, true);
126 
127 	if (priv->phydev == NULL) {
128 		link_info = cvmx_helper_link_autoconf(priv->port);
129 		priv->link_info = link_info.u64;
130 	}
131 
132 	if (use_global_register_lock)
133 		spin_unlock_irqrestore(&global_register_lock, flags);
134 	else
135 		mutex_unlock(&priv->phydev->bus->mdio_lock);
136 
137 	if (priv->phydev == NULL) {
138 		/* Tell core. */
139 		if (link_info.s.link_up) {
140 			if (!netif_carrier_ok(dev))
141 				netif_carrier_on(dev);
142 		} else if (netif_carrier_ok(dev)) {
143 			netif_carrier_off(dev);
144 		}
145 		cvm_oct_note_carrier(priv, link_info);
146 	}
147 }
148 
149 static int cmv_oct_rgmii_gmx_interrupt(int interface)
150 {
151 	int index;
152 	int count = 0;
153 
154 	/* Loop through every port of this interface */
155 	for (index = 0;
156 	     index < cvmx_helper_ports_on_interface(interface);
157 	     index++) {
158 		union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg;
159 
160 		/* Read the GMX interrupt status bits */
161 		gmx_rx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
162 					  (index, interface));
163 		gmx_rx_int_reg.u64 &= cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
164 					  (index, interface));
165 
166 		/* Poll the port if inband status changed */
167 		if (gmx_rx_int_reg.s.phy_dupx || gmx_rx_int_reg.s.phy_link ||
168 		    gmx_rx_int_reg.s.phy_spd) {
169 			struct net_device *dev =
170 				    cvm_oct_device[cvmx_helper_get_ipd_port
171 						   (interface, index)];
172 			struct octeon_ethernet *priv = netdev_priv(dev);
173 
174 			if (dev && !atomic_read(&cvm_oct_poll_queue_stopping))
175 				queue_work(cvm_oct_poll_queue,
176 					   &priv->port_work);
177 
178 			gmx_rx_int_reg.u64 = 0;
179 			gmx_rx_int_reg.s.phy_dupx = 1;
180 			gmx_rx_int_reg.s.phy_link = 1;
181 			gmx_rx_int_reg.s.phy_spd = 1;
182 			cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
183 				       gmx_rx_int_reg.u64);
184 			count++;
185 		}
186 	}
187 	return count;
188 }
189 
190 static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id)
191 {
192 	union cvmx_npi_rsl_int_blocks rsl_int_blocks;
193 	int count = 0;
194 
195 	rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);
196 
197 	/* Check and see if this interrupt was caused by the GMX0 block */
198 	if (rsl_int_blocks.s.gmx0)
199 		count += cmv_oct_rgmii_gmx_interrupt(0);
200 
201 	/* Check and see if this interrupt was caused by the GMX1 block */
202 	if (rsl_int_blocks.s.gmx1)
203 		count += cmv_oct_rgmii_gmx_interrupt(1);
204 
205 	return count ? IRQ_HANDLED : IRQ_NONE;
206 }
207 
208 int cvm_oct_rgmii_open(struct net_device *dev)
209 {
210 	return cvm_oct_common_open(dev, cvm_oct_rgmii_poll, false);
211 }
212 
213 static void cvm_oct_rgmii_immediate_poll(struct work_struct *work)
214 {
215 	struct octeon_ethernet *priv =
216 		container_of(work, struct octeon_ethernet, port_work);
217 	cvm_oct_rgmii_poll(cvm_oct_device[priv->port]);
218 }
219 
220 int cvm_oct_rgmii_init(struct net_device *dev)
221 {
222 	struct octeon_ethernet *priv = netdev_priv(dev);
223 	int r;
224 
225 	cvm_oct_common_init(dev);
226 	INIT_WORK(&priv->port_work, cvm_oct_rgmii_immediate_poll);
227 	/*
228 	 * Due to GMX errata in CN3XXX series chips, it is necessary
229 	 * to take the link down immediately when the PHY changes
230 	 * state. In order to do this we call the poll function every
231 	 * time the RGMII inband status changes.  This may cause
232 	 * problems if the PHY doesn't implement inband status
233 	 * properly.
234 	 */
235 	if (number_rgmii_ports == 0) {
236 		r = request_irq(OCTEON_IRQ_RML, cvm_oct_rgmii_rml_interrupt,
237 				IRQF_SHARED, "RGMII", &number_rgmii_ports);
238 		if (r != 0)
239 			return r;
240 	}
241 	number_rgmii_ports++;
242 
243 	/*
244 	 * Only true RGMII ports need to be polled. In GMII mode, port
245 	 * 0 is really a RGMII port.
246 	 */
247 	if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
248 	     && (priv->port == 0))
249 	    || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
250 
251 		if (!octeon_is_simulation()) {
252 
253 			union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
254 			int interface = INTERFACE(priv->port);
255 			int index = INDEX(priv->port);
256 
257 			/*
258 			 * Enable interrupts on inband status changes
259 			 * for this port.
260 			 */
261 			gmx_rx_int_en.u64 = 0;
262 			gmx_rx_int_en.s.phy_dupx = 1;
263 			gmx_rx_int_en.s.phy_link = 1;
264 			gmx_rx_int_en.s.phy_spd = 1;
265 			cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
266 				       gmx_rx_int_en.u64);
267 		}
268 	}
269 
270 	return 0;
271 }
272 
273 void cvm_oct_rgmii_uninit(struct net_device *dev)
274 {
275 	struct octeon_ethernet *priv = netdev_priv(dev);
276 
277 	cvm_oct_common_uninit(dev);
278 
279 	/*
280 	 * Only true RGMII ports need to be polled. In GMII mode, port
281 	 * 0 is really a RGMII port.
282 	 */
283 	if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
284 	     && (priv->port == 0))
285 	    || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
286 
287 		if (!octeon_is_simulation()) {
288 
289 			union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
290 			int interface = INTERFACE(priv->port);
291 			int index = INDEX(priv->port);
292 
293 			/*
294 			 * Disable interrupts on inband status changes
295 			 * for this port.
296 			 */
297 			gmx_rx_int_en.u64 =
298 			    cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
299 					  (index, interface));
300 			gmx_rx_int_en.s.phy_dupx = 0;
301 			gmx_rx_int_en.s.phy_link = 0;
302 			gmx_rx_int_en.s.phy_spd = 0;
303 			cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
304 				       gmx_rx_int_en.u64);
305 		}
306 	}
307 
308 	/* Remove the interrupt handler when the last port is removed. */
309 	number_rgmii_ports--;
310 	if (number_rgmii_ports == 0)
311 		free_irq(OCTEON_IRQ_RML, &number_rgmii_ports);
312 	cancel_work_sync(&priv->port_work);
313 }
314