Linux-libre 4.9.123-gnu
[librecmc/linux-libre.git] / drivers / staging / octeon / ethernet-rgmii.c
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 void cvm_oct_set_hw_preamble(struct octeon_ethernet *priv, bool enable)
34 {
35         union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
36         union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
37         union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
38         int interface = INTERFACE(priv->port);
39         int index = INDEX(priv->port);
40
41         /* Set preamble checking. */
42         gmxx_rxx_frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index,
43                                                                    interface));
44         gmxx_rxx_frm_ctl.s.pre_chk = enable;
45         cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface),
46                        gmxx_rxx_frm_ctl.u64);
47
48         /* Set FCS stripping. */
49         ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
50         if (enable)
51                 ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port;
52         else
53                 ipd_sub_port_fcs.s.port_bit &=
54                                         0xffffffffull ^ (1ull << priv->port);
55         cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64);
56
57         /* Clear any error bits. */
58         gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index,
59                                                                    interface));
60         cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
61                        gmxx_rxx_int_reg.u64);
62 }
63
64 static void cvm_oct_check_preamble_errors(struct net_device *dev)
65 {
66         struct octeon_ethernet *priv = netdev_priv(dev);
67         cvmx_helper_link_info_t link_info;
68         unsigned long flags;
69
70         link_info.u64 = priv->link_info;
71
72         /*
73          * Take the global register lock since we are going to
74          * touch registers that affect more than one port.
75          */
76         spin_lock_irqsave(&global_register_lock, flags);
77
78         if (link_info.s.speed == 10 && priv->last_speed == 10) {
79                 /*
80                  * Read the GMXX_RXX_INT_REG[PCTERR] bit and see if we are
81                  * 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
87                 gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
88                                                         (index, interface));
89                 if (gmxx_rxx_int_reg.s.pcterr) {
90                         /*
91                          * We are getting preamble errors at 10Mbps. Most
92                          * likely the PHY is giving us packets with misaligned
93                          * preambles. In order to get these packets we need to
94                          * disable preamble checking and do it in software.
95                          */
96                         cvm_oct_set_hw_preamble(priv, false);
97                         printk_ratelimited("%s: Using 10Mbps with software preamble removal\n",
98                                            dev->name);
99                 }
100         } else {
101                 /*
102                  * Since the 10Mbps preamble workaround is allowed we need to
103                  * enable preamble checking, FCS stripping, and clear error
104                  * bits on every speed change. If errors occur during 10Mbps
105                  * operation the above code will change this stuff
106                  */
107                 if (priv->last_speed != link_info.s.speed)
108                         cvm_oct_set_hw_preamble(priv, true);
109                 priv->last_speed = link_info.s.speed;
110         }
111         spin_unlock_irqrestore(&global_register_lock, flags);
112 }
113
114 static void cvm_oct_rgmii_poll(struct net_device *dev)
115 {
116         struct octeon_ethernet *priv = netdev_priv(dev);
117         cvmx_helper_link_info_t link_info;
118         bool status_change;
119
120         link_info = cvmx_helper_link_get(priv->port);
121         if (priv->link_info != link_info.u64 &&
122             cvmx_helper_link_set(priv->port, link_info))
123                 link_info.u64 = priv->link_info;
124         status_change = priv->link_info != link_info.u64;
125         priv->link_info = link_info.u64;
126
127         cvm_oct_check_preamble_errors(dev);
128
129         if (likely(!status_change))
130                 return;
131
132         /* Tell core. */
133         if (link_info.s.link_up) {
134                 if (!netif_carrier_ok(dev))
135                         netif_carrier_on(dev);
136         } else if (netif_carrier_ok(dev)) {
137                 netif_carrier_off(dev);
138         }
139         cvm_oct_note_carrier(priv, link_info);
140 }
141
142 int cvm_oct_rgmii_open(struct net_device *dev)
143 {
144         struct octeon_ethernet *priv = netdev_priv(dev);
145         int ret;
146
147         ret = cvm_oct_common_open(dev, cvm_oct_rgmii_poll);
148         if (ret)
149                 return ret;
150
151         if (dev->phydev) {
152                 /*
153                  * In phydev mode, we need still periodic polling for the
154                  * preamble error checking, and we also need to call this
155                  * function on every link state change.
156                  *
157                  * Only true RGMII ports need to be polled. In GMII mode, port
158                  * 0 is really a RGMII port.
159                  */
160                 if ((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII &&
161                      priv->port  == 0) ||
162                     (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
163                         priv->poll = cvm_oct_check_preamble_errors;
164                         cvm_oct_check_preamble_errors(dev);
165                 }
166         }
167
168         return 0;
169 }