Merge branch 'master' into for-next
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / octeon / ethernet-rgmii.c
1 /*********************************************************************
2 * Author: Cavium Networks
3 *
4 * Contact: support@caviumnetworks.com
5 * This file is part of the OCTEON SDK
6 *
7 * Copyright (c) 2003-2007 Cavium Networks
8 *
9 * This file is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License, Version 2, as
11 * published by the Free Software Foundation.
12 *
13 * This file is distributed in the hope that it will be useful, but
14 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
16 * NONINFRINGEMENT. See the GNU General Public License for more
17 * details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this file; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 * or visit http://www.gnu.org/licenses/.
23 *
24 * This file may also be available under a different license from Cavium.
25 * Contact Cavium Networks for more information
26 **********************************************************************/
27 #include <linux/kernel.h>
28 #include <linux/netdevice.h>
29 #include <linux/phy.h>
30 #include <net/dst.h>
31
32 #include <asm/octeon/octeon.h>
33
34 #include "ethernet-defines.h"
35 #include "octeon-ethernet.h"
36 #include "ethernet-util.h"
37
38 #include "cvmx-helper.h"
39
40 #include <asm/octeon/cvmx-ipd-defs.h>
41 #include <asm/octeon/cvmx-npi-defs.h>
42 #include "cvmx-gmxx-defs.h"
43
44 DEFINE_SPINLOCK(global_register_lock);
45
46 static int number_rgmii_ports;
47
48 static void cvm_oct_rgmii_poll(struct net_device *dev)
49 {
50 struct octeon_ethernet *priv = netdev_priv(dev);
51 unsigned long flags = 0;
52 cvmx_helper_link_info_t link_info;
53 int use_global_register_lock = (priv->phydev == NULL);
54
55 BUG_ON(in_interrupt());
56 if (use_global_register_lock) {
57 /*
58 * Take the global register lock since we are going to
59 * touch registers that affect more than one port.
60 */
61 spin_lock_irqsave(&global_register_lock, flags);
62 } else {
63 mutex_lock(&priv->phydev->bus->mdio_lock);
64 }
65
66 link_info = cvmx_helper_link_get(priv->port);
67 if (link_info.u64 == priv->link_info) {
68
69 /*
70 * If the 10Mbps preamble workaround is supported and we're
71 * at 10Mbps we may need to do some special checking.
72 */
73 if (USE_10MBPS_PREAMBLE_WORKAROUND && (link_info.s.speed == 10)) {
74
75 /*
76 * Read the GMXX_RXX_INT_REG[PCTERR] bit and
77 * see if we are getting preamble errors.
78 */
79 int interface = INTERFACE(priv->port);
80 int index = INDEX(priv->port);
81 union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
82 gmxx_rxx_int_reg.u64 =
83 cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
84 (index, interface));
85 if (gmxx_rxx_int_reg.s.pcterr) {
86
87 /*
88 * We are getting preamble errors at
89 * 10Mbps. Most likely the PHY is
90 * giving us packets with mis aligned
91 * preambles. In order to get these
92 * packets we need to disable preamble
93 * checking and do it in software.
94 */
95 union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
96 union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
97
98 /* Disable preamble checking */
99 gmxx_rxx_frm_ctl.u64 =
100 cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL
101 (index, interface));
102 gmxx_rxx_frm_ctl.s.pre_chk = 0;
103 cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL
104 (index, interface),
105 gmxx_rxx_frm_ctl.u64);
106
107 /* Disable FCS stripping */
108 ipd_sub_port_fcs.u64 =
109 cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
110 ipd_sub_port_fcs.s.port_bit &=
111 0xffffffffull ^ (1ull << priv->port);
112 cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS,
113 ipd_sub_port_fcs.u64);
114
115 /* Clear any error bits */
116 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
117 (index, interface),
118 gmxx_rxx_int_reg.u64);
119 DEBUGPRINT("%s: Using 10Mbps with software "
120 "preamble removal\n",
121 dev->name);
122 }
123 }
124
125 if (use_global_register_lock)
126 spin_unlock_irqrestore(&global_register_lock, flags);
127 else
128 mutex_unlock(&priv->phydev->bus->mdio_lock);
129 return;
130 }
131
132 /* If the 10Mbps preamble workaround is allowed we need to on
133 preamble checking, FCS stripping, and clear error bits on
134 every speed change. If errors occur during 10Mbps operation
135 the above code will change this stuff */
136 if (USE_10MBPS_PREAMBLE_WORKAROUND) {
137
138 union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
139 union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
140 union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
141 int interface = INTERFACE(priv->port);
142 int index = INDEX(priv->port);
143
144 /* Enable preamble checking */
145 gmxx_rxx_frm_ctl.u64 =
146 cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface));
147 gmxx_rxx_frm_ctl.s.pre_chk = 1;
148 cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface),
149 gmxx_rxx_frm_ctl.u64);
150 /* Enable FCS stripping */
151 ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
152 ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port;
153 cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64);
154 /* Clear any error bits */
155 gmxx_rxx_int_reg.u64 =
156 cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface));
157 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
158 gmxx_rxx_int_reg.u64);
159 }
160 if (priv->phydev == NULL) {
161 link_info = cvmx_helper_link_autoconf(priv->port);
162 priv->link_info = link_info.u64;
163 }
164
165 if (use_global_register_lock)
166 spin_unlock_irqrestore(&global_register_lock, flags);
167 else {
168 mutex_unlock(&priv->phydev->bus->mdio_lock);
169 }
170
171 if (priv->phydev == NULL) {
172 /* Tell core. */
173 if (link_info.s.link_up) {
174 if (!netif_carrier_ok(dev))
175 netif_carrier_on(dev);
176 if (priv->queue != -1)
177 DEBUGPRINT("%s: %u Mbps %s duplex, "
178 "port %2d, queue %2d\n",
179 dev->name, link_info.s.speed,
180 (link_info.s.full_duplex) ?
181 "Full" : "Half",
182 priv->port, priv->queue);
183 else
184 DEBUGPRINT("%s: %u Mbps %s duplex, "
185 "port %2d, POW\n",
186 dev->name, link_info.s.speed,
187 (link_info.s.full_duplex) ?
188 "Full" : "Half",
189 priv->port);
190 } else {
191 if (netif_carrier_ok(dev))
192 netif_carrier_off(dev);
193 DEBUGPRINT("%s: Link down\n", dev->name);
194 }
195 }
196 }
197
198 static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id)
199 {
200 union cvmx_npi_rsl_int_blocks rsl_int_blocks;
201 int index;
202 irqreturn_t return_status = IRQ_NONE;
203
204 rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);
205
206 /* Check and see if this interrupt was caused by the GMX0 block */
207 if (rsl_int_blocks.s.gmx0) {
208
209 int interface = 0;
210 /* Loop through every port of this interface */
211 for (index = 0;
212 index < cvmx_helper_ports_on_interface(interface);
213 index++) {
214
215 /* Read the GMX interrupt status bits */
216 union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg;
217 gmx_rx_int_reg.u64 =
218 cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
219 (index, interface));
220 gmx_rx_int_reg.u64 &=
221 cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
222 (index, interface));
223 /* Poll the port if inband status changed */
224 if (gmx_rx_int_reg.s.phy_dupx
225 || gmx_rx_int_reg.s.phy_link
226 || gmx_rx_int_reg.s.phy_spd) {
227
228 struct net_device *dev =
229 cvm_oct_device[cvmx_helper_get_ipd_port
230 (interface, index)];
231 struct octeon_ethernet *priv = netdev_priv(dev);
232
233 if (dev && !atomic_read(&cvm_oct_poll_queue_stopping))
234 queue_work(cvm_oct_poll_queue, &priv->port_work);
235
236 gmx_rx_int_reg.u64 = 0;
237 gmx_rx_int_reg.s.phy_dupx = 1;
238 gmx_rx_int_reg.s.phy_link = 1;
239 gmx_rx_int_reg.s.phy_spd = 1;
240 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
241 (index, interface),
242 gmx_rx_int_reg.u64);
243 return_status = IRQ_HANDLED;
244 }
245 }
246 }
247
248 /* Check and see if this interrupt was caused by the GMX1 block */
249 if (rsl_int_blocks.s.gmx1) {
250
251 int interface = 1;
252 /* Loop through every port of this interface */
253 for (index = 0;
254 index < cvmx_helper_ports_on_interface(interface);
255 index++) {
256
257 /* Read the GMX interrupt status bits */
258 union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg;
259 gmx_rx_int_reg.u64 =
260 cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
261 (index, interface));
262 gmx_rx_int_reg.u64 &=
263 cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
264 (index, interface));
265 /* Poll the port if inband status changed */
266 if (gmx_rx_int_reg.s.phy_dupx
267 || gmx_rx_int_reg.s.phy_link
268 || gmx_rx_int_reg.s.phy_spd) {
269
270 struct net_device *dev =
271 cvm_oct_device[cvmx_helper_get_ipd_port
272 (interface, index)];
273 struct octeon_ethernet *priv = netdev_priv(dev);
274
275 if (dev && !atomic_read(&cvm_oct_poll_queue_stopping))
276 queue_work(cvm_oct_poll_queue, &priv->port_work);
277
278 gmx_rx_int_reg.u64 = 0;
279 gmx_rx_int_reg.s.phy_dupx = 1;
280 gmx_rx_int_reg.s.phy_link = 1;
281 gmx_rx_int_reg.s.phy_spd = 1;
282 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
283 (index, interface),
284 gmx_rx_int_reg.u64);
285 return_status = IRQ_HANDLED;
286 }
287 }
288 }
289 return return_status;
290 }
291
292 int cvm_oct_rgmii_open(struct net_device *dev)
293 {
294 union cvmx_gmxx_prtx_cfg gmx_cfg;
295 struct octeon_ethernet *priv = netdev_priv(dev);
296 int interface = INTERFACE(priv->port);
297 int index = INDEX(priv->port);
298 cvmx_helper_link_info_t link_info;
299
300 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
301 gmx_cfg.s.en = 1;
302 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
303
304 if (!octeon_is_simulation()) {
305 link_info = cvmx_helper_link_get(priv->port);
306 if (!link_info.s.link_up)
307 netif_carrier_off(dev);
308 }
309
310 return 0;
311 }
312
313 int cvm_oct_rgmii_stop(struct net_device *dev)
314 {
315 union cvmx_gmxx_prtx_cfg gmx_cfg;
316 struct octeon_ethernet *priv = netdev_priv(dev);
317 int interface = INTERFACE(priv->port);
318 int index = INDEX(priv->port);
319
320 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
321 gmx_cfg.s.en = 0;
322 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
323 return 0;
324 }
325
326 static void cvm_oct_rgmii_immediate_poll(struct work_struct *work)
327 {
328 struct octeon_ethernet *priv = container_of(work, struct octeon_ethernet, port_work);
329 cvm_oct_rgmii_poll(cvm_oct_device[priv->port]);
330 }
331
332 int cvm_oct_rgmii_init(struct net_device *dev)
333 {
334 struct octeon_ethernet *priv = netdev_priv(dev);
335 int r;
336
337 cvm_oct_common_init(dev);
338 dev->netdev_ops->ndo_stop(dev);
339 INIT_WORK(&priv->port_work, cvm_oct_rgmii_immediate_poll);
340 /*
341 * Due to GMX errata in CN3XXX series chips, it is necessary
342 * to take the link down immediately when the PHY changes
343 * state. In order to do this we call the poll function every
344 * time the RGMII inband status changes. This may cause
345 * problems if the PHY doesn't implement inband status
346 * properly.
347 */
348 if (number_rgmii_ports == 0) {
349 r = request_irq(OCTEON_IRQ_RML, cvm_oct_rgmii_rml_interrupt,
350 IRQF_SHARED, "RGMII", &number_rgmii_ports);
351 if (r != 0)
352 return r;
353 }
354 number_rgmii_ports++;
355
356 /*
357 * Only true RGMII ports need to be polled. In GMII mode, port
358 * 0 is really a RGMII port.
359 */
360 if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
361 && (priv->port == 0))
362 || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
363
364 if (!octeon_is_simulation()) {
365
366 union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
367 int interface = INTERFACE(priv->port);
368 int index = INDEX(priv->port);
369
370 /*
371 * Enable interrupts on inband status changes
372 * for this port.
373 */
374 gmx_rx_int_en.u64 =
375 cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
376 (index, interface));
377 gmx_rx_int_en.s.phy_dupx = 1;
378 gmx_rx_int_en.s.phy_link = 1;
379 gmx_rx_int_en.s.phy_spd = 1;
380 cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
381 gmx_rx_int_en.u64);
382 priv->poll = cvm_oct_rgmii_poll;
383 }
384 }
385
386 return 0;
387 }
388
389 void cvm_oct_rgmii_uninit(struct net_device *dev)
390 {
391 struct octeon_ethernet *priv = netdev_priv(dev);
392 cvm_oct_common_uninit(dev);
393
394 /*
395 * Only true RGMII ports need to be polled. In GMII mode, port
396 * 0 is really a RGMII port.
397 */
398 if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
399 && (priv->port == 0))
400 || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
401
402 if (!octeon_is_simulation()) {
403
404 union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
405 int interface = INTERFACE(priv->port);
406 int index = INDEX(priv->port);
407
408 /*
409 * Disable interrupts on inband status changes
410 * for this port.
411 */
412 gmx_rx_int_en.u64 =
413 cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
414 (index, interface));
415 gmx_rx_int_en.s.phy_dupx = 0;
416 gmx_rx_int_en.s.phy_link = 0;
417 gmx_rx_int_en.s.phy_spd = 0;
418 cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
419 gmx_rx_int_en.u64);
420 }
421 }
422
423 /* Remove the interrupt handler when the last port is removed. */
424 number_rgmii_ports--;
425 if (number_rgmii_ports == 0)
426 free_irq(OCTEON_IRQ_RML, &number_rgmii_ports);
427 cancel_work_sync(&priv->port_work);
428 }