These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / 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 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);
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 }