1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <linux/kernel.h>
28#include <linux/netdevice.h>
29#include <linux/mii.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
44DEFINE_SPINLOCK(global_register_lock);
45
46static int number_rgmii_ports;
47
48static void cvm_oct_rgmii_poll(struct net_device *dev)
49{
50 struct octeon_ethernet *priv = netdev_priv(dev);
51 unsigned long flags;
52 cvmx_helper_link_info_t link_info;
53
54
55
56
57
58 spin_lock_irqsave(&global_register_lock, flags);
59
60 link_info = cvmx_helper_link_get(priv->port);
61 if (link_info.u64 == priv->link_info) {
62
63
64
65
66
67 if (USE_10MBPS_PREAMBLE_WORKAROUND && (link_info.s.speed == 10)) {
68
69
70
71
72
73 int interface = INTERFACE(priv->port);
74 int index = INDEX(priv->port);
75 union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
76 gmxx_rxx_int_reg.u64 =
77 cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
78 (index, interface));
79 if (gmxx_rxx_int_reg.s.pcterr) {
80
81
82
83
84
85
86
87
88
89 union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
90 union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
91
92
93 gmxx_rxx_frm_ctl.u64 =
94 cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL
95 (index, interface));
96 gmxx_rxx_frm_ctl.s.pre_chk = 0;
97 cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL
98 (index, interface),
99 gmxx_rxx_frm_ctl.u64);
100
101
102 ipd_sub_port_fcs.u64 =
103 cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
104 ipd_sub_port_fcs.s.port_bit &=
105 0xffffffffull ^ (1ull << priv->port);
106 cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS,
107 ipd_sub_port_fcs.u64);
108
109
110 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
111 (index, interface),
112 gmxx_rxx_int_reg.u64);
113 DEBUGPRINT("%s: Using 10Mbps with software "
114 "preamble removal\n",
115 dev->name);
116 }
117 }
118 spin_unlock_irqrestore(&global_register_lock, flags);
119 return;
120 }
121
122
123
124
125
126 if (USE_10MBPS_PREAMBLE_WORKAROUND) {
127
128 union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
129 union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
130 union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
131 int interface = INTERFACE(priv->port);
132 int index = INDEX(priv->port);
133
134
135 gmxx_rxx_frm_ctl.u64 =
136 cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface));
137 gmxx_rxx_frm_ctl.s.pre_chk = 1;
138 cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface),
139 gmxx_rxx_frm_ctl.u64);
140
141 ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
142 ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port;
143 cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64);
144
145 gmxx_rxx_int_reg.u64 =
146 cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface));
147 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
148 gmxx_rxx_int_reg.u64);
149 }
150
151 link_info = cvmx_helper_link_autoconf(priv->port);
152 priv->link_info = link_info.u64;
153 spin_unlock_irqrestore(&global_register_lock, flags);
154
155
156 if (link_info.s.link_up) {
157
158 if (!netif_carrier_ok(dev))
159 netif_carrier_on(dev);
160 if (priv->queue != -1)
161 DEBUGPRINT
162 ("%s: %u Mbps %s duplex, port %2d, queue %2d\n",
163 dev->name, link_info.s.speed,
164 (link_info.s.full_duplex) ? "Full" : "Half",
165 priv->port, priv->queue);
166 else
167 DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n",
168 dev->name, link_info.s.speed,
169 (link_info.s.full_duplex) ? "Full" : "Half",
170 priv->port);
171 } else {
172
173 if (netif_carrier_ok(dev))
174 netif_carrier_off(dev);
175 DEBUGPRINT("%s: Link down\n", dev->name);
176 }
177}
178
179static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id)
180{
181 union cvmx_npi_rsl_int_blocks rsl_int_blocks;
182 int index;
183 irqreturn_t return_status = IRQ_NONE;
184
185 rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);
186
187
188 if (rsl_int_blocks.s.gmx0) {
189
190 int interface = 0;
191
192 for (index = 0;
193 index < cvmx_helper_ports_on_interface(interface);
194 index++) {
195
196
197 union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg;
198 gmx_rx_int_reg.u64 =
199 cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
200 (index, interface));
201 gmx_rx_int_reg.u64 &=
202 cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
203 (index, interface));
204
205 if (gmx_rx_int_reg.s.phy_dupx
206 || gmx_rx_int_reg.s.phy_link
207 || gmx_rx_int_reg.s.phy_spd) {
208
209 struct net_device *dev =
210 cvm_oct_device[cvmx_helper_get_ipd_port
211 (interface, index)];
212 if (dev)
213 cvm_oct_rgmii_poll(dev);
214 gmx_rx_int_reg.u64 = 0;
215 gmx_rx_int_reg.s.phy_dupx = 1;
216 gmx_rx_int_reg.s.phy_link = 1;
217 gmx_rx_int_reg.s.phy_spd = 1;
218 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
219 (index, interface),
220 gmx_rx_int_reg.u64);
221 return_status = IRQ_HANDLED;
222 }
223 }
224 }
225
226
227 if (rsl_int_blocks.s.gmx1) {
228
229 int interface = 1;
230
231 for (index = 0;
232 index < cvmx_helper_ports_on_interface(interface);
233 index++) {
234
235
236 union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg;
237 gmx_rx_int_reg.u64 =
238 cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
239 (index, interface));
240 gmx_rx_int_reg.u64 &=
241 cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
242 (index, interface));
243
244 if (gmx_rx_int_reg.s.phy_dupx
245 || gmx_rx_int_reg.s.phy_link
246 || gmx_rx_int_reg.s.phy_spd) {
247
248 struct net_device *dev =
249 cvm_oct_device[cvmx_helper_get_ipd_port
250 (interface, index)];
251 if (dev)
252 cvm_oct_rgmii_poll(dev);
253 gmx_rx_int_reg.u64 = 0;
254 gmx_rx_int_reg.s.phy_dupx = 1;
255 gmx_rx_int_reg.s.phy_link = 1;
256 gmx_rx_int_reg.s.phy_spd = 1;
257 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
258 (index, interface),
259 gmx_rx_int_reg.u64);
260 return_status = IRQ_HANDLED;
261 }
262 }
263 }
264 return return_status;
265}
266
267int cvm_oct_rgmii_open(struct net_device *dev)
268{
269 union cvmx_gmxx_prtx_cfg gmx_cfg;
270 struct octeon_ethernet *priv = netdev_priv(dev);
271 int interface = INTERFACE(priv->port);
272 int index = INDEX(priv->port);
273 cvmx_helper_link_info_t link_info;
274
275 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
276 gmx_cfg.s.en = 1;
277 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
278
279 if (!octeon_is_simulation()) {
280 link_info = cvmx_helper_link_get(priv->port);
281 if (!link_info.s.link_up)
282 netif_carrier_off(dev);
283 }
284
285 return 0;
286}
287
288int cvm_oct_rgmii_stop(struct net_device *dev)
289{
290 union cvmx_gmxx_prtx_cfg gmx_cfg;
291 struct octeon_ethernet *priv = netdev_priv(dev);
292 int interface = INTERFACE(priv->port);
293 int index = INDEX(priv->port);
294
295 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
296 gmx_cfg.s.en = 0;
297 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
298 return 0;
299}
300
301int cvm_oct_rgmii_init(struct net_device *dev)
302{
303 struct octeon_ethernet *priv = netdev_priv(dev);
304 int r;
305
306 cvm_oct_common_init(dev);
307 dev->netdev_ops->ndo_stop(dev);
308
309
310
311
312
313
314
315
316
317 if (number_rgmii_ports == 0) {
318 r = request_irq(OCTEON_IRQ_RML, cvm_oct_rgmii_rml_interrupt,
319 IRQF_SHARED, "RGMII", &number_rgmii_ports);
320 }
321 number_rgmii_ports++;
322
323
324
325
326
327 if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
328 && (priv->port == 0))
329 || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
330
331 if (!octeon_is_simulation()) {
332
333 union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
334 int interface = INTERFACE(priv->port);
335 int index = INDEX(priv->port);
336
337
338
339
340
341 gmx_rx_int_en.u64 =
342 cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
343 (index, interface));
344 gmx_rx_int_en.s.phy_dupx = 1;
345 gmx_rx_int_en.s.phy_link = 1;
346 gmx_rx_int_en.s.phy_spd = 1;
347 cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
348 gmx_rx_int_en.u64);
349 priv->poll = cvm_oct_rgmii_poll;
350 }
351 }
352
353 return 0;
354}
355
356void cvm_oct_rgmii_uninit(struct net_device *dev)
357{
358 struct octeon_ethernet *priv = netdev_priv(dev);
359 cvm_oct_common_uninit(dev);
360
361
362
363
364
365 if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII)
366 && (priv->port == 0))
367 || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
368
369 if (!octeon_is_simulation()) {
370
371 union cvmx_gmxx_rxx_int_en gmx_rx_int_en;
372 int interface = INTERFACE(priv->port);
373 int index = INDEX(priv->port);
374
375
376
377
378
379 gmx_rx_int_en.u64 =
380 cvmx_read_csr(CVMX_GMXX_RXX_INT_EN
381 (index, interface));
382 gmx_rx_int_en.s.phy_dupx = 0;
383 gmx_rx_int_en.s.phy_link = 0;
384 gmx_rx_int_en.s.phy_spd = 0;
385 cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface),
386 gmx_rx_int_en.u64);
387 }
388 }
389
390
391 number_rgmii_ports--;
392 if (number_rgmii_ports == 0)
393 free_irq(OCTEON_IRQ_RML, &number_rgmii_ports);
394}
395