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