Root/target/linux/octeon/patches-2.6.30/006-octeon_mgmt_driver.patch

1Signed-off-by: David Daney <ddaney@caviumnetworks.com>
2---
3 arch/mips/include/asm/octeon/cvmx-mdio.h | 577 +++++++++++++++++++++
4 drivers/net/Kconfig | 8 +
5 drivers/net/Makefile | 1 +
6 drivers/net/octeon/Makefile | 11 +
7 drivers/net/octeon/cvmx-mgmt-port.c | 818 ++++++++++++++++++++++++++++++
8 drivers/net/octeon/cvmx-mgmt-port.h | 168 ++++++
9 drivers/net/octeon/octeon-mgmt-port.c | 389 ++++++++++++++
10 7 files changed, 1972 insertions(+), 0 deletions(-)
11 create mode 100644 arch/mips/include/asm/octeon/cvmx-mdio.h
12 create mode 100644 drivers/net/octeon/Makefile
13 create mode 100644 drivers/net/octeon/cvmx-mgmt-port.c
14 create mode 100644 drivers/net/octeon/cvmx-mgmt-port.h
15 create mode 100644 drivers/net/octeon/octeon-mgmt-port.c
16
17--- /dev/null
18+++ b/arch/mips/include/asm/octeon/cvmx-mdio.h
19@@ -0,0 +1,577 @@
20+/***********************license start***************
21+ * Author: Cavium Networks
22+ *
23+ * Contact: support@caviumnetworks.com
24+ * This file is part of the OCTEON SDK
25+ *
26+ * Copyright (c) 2003-2008 Cavium Networks
27+ *
28+ * This file is free software; you can redistribute it and/or modify
29+ * it under the terms of the GNU General Public License, Version 2, as
30+ * published by the Free Software Foundation.
31+ *
32+ * This file is distributed in the hope that it will be useful, but
33+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
34+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
35+ * NONINFRINGEMENT. See the GNU General Public License for more
36+ * details.
37+ *
38+ * You should have received a copy of the GNU General Public License
39+ * along with this file; if not, write to the Free Software
40+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
41+ * or visit http://www.gnu.org/licenses/.
42+ *
43+ * This file may also be available under a different license from Cavium.
44+ * Contact Cavium Networks for more information
45+ ***********************license end**************************************/
46+
47+/**
48+ *
49+ * Interface to the SMI/MDIO hardware, including support for both IEEE 802.3
50+ * clause 22 and clause 45 operations.
51+ *
52+ */
53+
54+#ifndef __CVMX_MIO_H__
55+#define __CVMX_MIO_H__
56+
57+#include "cvmx-smix-defs.h"
58+
59+/**
60+ * PHY register 0 from the 802.3 spec
61+ */
62+#define CVMX_MDIO_PHY_REG_CONTROL 0
63+union cvmx_mdio_phy_reg_control {
64+ uint16_t u16;
65+ struct {
66+ uint16_t reset:1;
67+ uint16_t loopback:1;
68+ uint16_t speed_lsb:1;
69+ uint16_t autoneg_enable:1;
70+ uint16_t power_down:1;
71+ uint16_t isolate:1;
72+ uint16_t restart_autoneg:1;
73+ uint16_t duplex:1;
74+ uint16_t collision_test:1;
75+ uint16_t speed_msb:1;
76+ uint16_t unidirectional_enable:1;
77+ uint16_t reserved_0_4:5;
78+ } s;
79+};
80+
81+/**
82+ * PHY register 1 from the 802.3 spec
83+ */
84+#define CVMX_MDIO_PHY_REG_STATUS 1
85+union cvmx_mdio_phy_reg_status {
86+ uint16_t u16;
87+ struct {
88+ uint16_t capable_100base_t4:1;
89+ uint16_t capable_100base_x_full:1;
90+ uint16_t capable_100base_x_half:1;
91+ uint16_t capable_10_full:1;
92+ uint16_t capable_10_half:1;
93+ uint16_t capable_100base_t2_full:1;
94+ uint16_t capable_100base_t2_half:1;
95+ uint16_t capable_extended_status:1;
96+ uint16_t capable_unidirectional:1;
97+ uint16_t capable_mf_preamble_suppression:1;
98+ uint16_t autoneg_complete:1;
99+ uint16_t remote_fault:1;
100+ uint16_t capable_autoneg:1;
101+ uint16_t link_status:1;
102+ uint16_t jabber_detect:1;
103+ uint16_t capable_extended_registers:1;
104+
105+ } s;
106+};
107+
108+/**
109+ * PHY register 2 from the 802.3 spec
110+ */
111+#define CVMX_MDIO_PHY_REG_ID1 2
112+union cvmx_mdio_phy_reg_id1 {
113+ uint16_t u16;
114+ struct {
115+ uint16_t oui_bits_3_18;
116+ } s;
117+};
118+
119+/**
120+ * PHY register 3 from the 802.3 spec
121+ */
122+#define CVMX_MDIO_PHY_REG_ID2 3
123+union cvmx_mdio_phy_reg_id2 {
124+ uint16_t u16;
125+ struct {
126+ uint16_t oui_bits_19_24:6;
127+ uint16_t model:6;
128+ uint16_t revision:4;
129+ } s;
130+};
131+
132+/**
133+ * PHY register 4 from the 802.3 spec
134+ */
135+#define CVMX_MDIO_PHY_REG_AUTONEG_ADVER 4
136+union cvmx_mdio_phy_reg_autoneg_adver {
137+ uint16_t u16;
138+ struct {
139+ uint16_t next_page:1;
140+ uint16_t reserved_14:1;
141+ uint16_t remote_fault:1;
142+ uint16_t reserved_12:1;
143+ uint16_t asymmetric_pause:1;
144+ uint16_t pause:1;
145+ uint16_t advert_100base_t4:1;
146+ uint16_t advert_100base_tx_full:1;
147+ uint16_t advert_100base_tx_half:1;
148+ uint16_t advert_10base_tx_full:1;
149+ uint16_t advert_10base_tx_half:1;
150+ uint16_t selector:5;
151+ } s;
152+};
153+
154+/**
155+ * PHY register 5 from the 802.3 spec
156+ */
157+#define CVMX_MDIO_PHY_REG_LINK_PARTNER_ABILITY 5
158+union cvmx_mdio_phy_reg_link_partner_ability {
159+ uint16_t u16;
160+ struct {
161+ uint16_t next_page:1;
162+ uint16_t ack:1;
163+ uint16_t remote_fault:1;
164+ uint16_t reserved_12:1;
165+ uint16_t asymmetric_pause:1;
166+ uint16_t pause:1;
167+ uint16_t advert_100base_t4:1;
168+ uint16_t advert_100base_tx_full:1;
169+ uint16_t advert_100base_tx_half:1;
170+ uint16_t advert_10base_tx_full:1;
171+ uint16_t advert_10base_tx_half:1;
172+ uint16_t selector:5;
173+ } s;
174+};
175+
176+/**
177+ * PHY register 6 from the 802.3 spec
178+ */
179+#define CVMX_MDIO_PHY_REG_AUTONEG_EXPANSION 6
180+union cvmx_mdio_phy_reg_autoneg_expansion {
181+ uint16_t u16;
182+ struct {
183+ uint16_t reserved_5_15:11;
184+ uint16_t parallel_detection_fault:1;
185+ uint16_t link_partner_next_page_capable:1;
186+ uint16_t local_next_page_capable:1;
187+ uint16_t page_received:1;
188+ uint16_t link_partner_autoneg_capable:1;
189+
190+ } s;
191+};
192+
193+/**
194+ * PHY register 9 from the 802.3 spec
195+ */
196+#define CVMX_MDIO_PHY_REG_CONTROL_1000 9
197+union cvmx_mdio_phy_reg_control_1000 {
198+ uint16_t u16;
199+ struct {
200+ uint16_t test_mode:3;
201+ uint16_t manual_master_slave:1;
202+ uint16_t master:1;
203+ uint16_t port_type:1;
204+ uint16_t advert_1000base_t_full:1;
205+ uint16_t advert_1000base_t_half:1;
206+ uint16_t reserved_0_7:8;
207+ } s;
208+};
209+
210+/**
211+ * PHY register 10 from the 802.3 spec
212+ */
213+#define CVMX_MDIO_PHY_REG_STATUS_1000 10
214+union cvmx_mdio_phy_reg_status_1000 {
215+ uint16_t u16;
216+ struct {
217+ uint16_t master_slave_fault:1;
218+ uint16_t is_master:1;
219+ uint16_t local_receiver_ok:1;
220+ uint16_t remote_receiver_ok:1;
221+ uint16_t remote_capable_1000base_t_full:1;
222+ uint16_t remote_capable_1000base_t_half:1;
223+ uint16_t reserved_8_9:2;
224+ uint16_t idle_error_count:8;
225+ } s;
226+};
227+
228+/**
229+ * PHY register 15 from the 802.3 spec
230+ */
231+#define CVMX_MDIO_PHY_REG_EXTENDED_STATUS 15
232+union cvmx_mdio_phy_reg_extended_status {
233+ uint16_t u16;
234+ struct {
235+ uint16_t capable_1000base_x_full:1;
236+ uint16_t capable_1000base_x_half:1;
237+ uint16_t capable_1000base_t_full:1;
238+ uint16_t capable_1000base_t_half:1;
239+ uint16_t reserved_0_11:12;
240+ } s;
241+};
242+
243+/**
244+ * PHY register 13 from the 802.3 spec
245+ */
246+#define CVMX_MDIO_PHY_REG_MMD_CONTROL 13
247+union cvmx_mdio_phy_reg_mmd_control {
248+ uint16_t u16;
249+ struct {
250+ uint16_t function:2;
251+ uint16_t reserved_5_13:9;
252+ uint16_t devad:5;
253+ } s;
254+};
255+
256+/**
257+ * PHY register 14 from the 802.3 spec
258+ */
259+#define CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA 14
260+union cvmx_mdio_phy_reg_mmd_address_data {
261+ uint16_t u16;
262+ struct {
263+ uint16_t address_data:16;
264+ } s;
265+};
266+
267+/* Operating request encodings. */
268+#define MDIO_CLAUSE_22_WRITE 0
269+#define MDIO_CLAUSE_22_READ 1
270+
271+#define MDIO_CLAUSE_45_ADDRESS 0
272+#define MDIO_CLAUSE_45_WRITE 1
273+#define MDIO_CLAUSE_45_READ_INC 2
274+#define MDIO_CLAUSE_45_READ 3
275+
276+/* MMD identifiers, mostly for accessing devices withing XENPAK modules. */
277+#define CVMX_MMD_DEVICE_PMA_PMD 1
278+#define CVMX_MMD_DEVICE_WIS 2
279+#define CVMX_MMD_DEVICE_PCS 3
280+#define CVMX_MMD_DEVICE_PHY_XS 4
281+#define CVMX_MMD_DEVICE_DTS_XS 5
282+#define CVMX_MMD_DEVICE_TC 6
283+#define CVMX_MMD_DEVICE_CL22_EXT 29
284+#define CVMX_MMD_DEVICE_VENDOR_1 30
285+#define CVMX_MMD_DEVICE_VENDOR_2 31
286+
287+/**
288+ * Perform an MII read. This function is used to read PHY
289+ * registers controlling auto negotiation.
290+ *
291+ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
292+ * support multiple busses.
293+ * @phy_id: The MII phy id
294+ * @location: Register location to read
295+ *
296+ * Returns Result from the read or -1 on failure
297+ */
298+static inline int cvmx_mdio_read(int bus_id, int phy_id, int location)
299+{
300+ union cvmx_smix_cmd smi_cmd;
301+ union cvmx_smix_rd_dat smi_rd;
302+ int timeout = 1000;
303+
304+ smi_cmd.u64 = 0;
305+ smi_cmd.s.phy_op = MDIO_CLAUSE_22_READ;
306+ smi_cmd.s.phy_adr = phy_id;
307+ smi_cmd.s.reg_adr = location;
308+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
309+
310+ do {
311+ cvmx_wait(1000);
312+ smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id));
313+ } while (smi_rd.s.pending && timeout--);
314+
315+ if (smi_rd.s.val)
316+ return smi_rd.s.dat;
317+ else
318+ return -1;
319+}
320+
321+/**
322+ * Perform an MII write. This function is used to write PHY
323+ * registers controlling auto negotiation.
324+ *
325+ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
326+ * support multiple busses.
327+ * @phy_id: The MII phy id
328+ * @location: Register location to write
329+ * @val: Value to write
330+ *
331+ * Returns -1 on error
332+ * 0 on success
333+ */
334+static inline int cvmx_mdio_write(int bus_id, int phy_id, int location, int val)
335+{
336+ union cvmx_smix_cmd smi_cmd;
337+ union cvmx_smix_wr_dat smi_wr;
338+ int timeout = 1000;
339+
340+ smi_wr.u64 = 0;
341+ smi_wr.s.dat = val;
342+ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
343+
344+ smi_cmd.u64 = 0;
345+ smi_cmd.s.phy_op = MDIO_CLAUSE_22_WRITE;
346+ smi_cmd.s.phy_adr = phy_id;
347+ smi_cmd.s.reg_adr = location;
348+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
349+
350+ do {
351+ cvmx_wait(1000);
352+ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
353+ } while (smi_wr.s.pending && --timeout);
354+ if (timeout <= 0)
355+ return -1;
356+
357+ return 0;
358+}
359+
360+/**
361+ * Perform an IEEE 802.3 clause 45 MII read using clause 22 operations. This
362+ * function is used to read PHY registers controlling auto negotiation.
363+ *
364+ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
365+ * support multiple busses.
366+ * @phy_id: The MII phy id
367+ * @device: MDIO Managable Device (MMD) id
368+ * @location: Register location to read
369+ *
370+ * Returns Result from the read or -1 on failure
371+ */
372+
373+static inline int cvmx_mdio_45_via_22_read(int bus_id, int phy_id, int device,
374+ int location)
375+{
376+ union cvmx_mdio_phy_reg_mmd_control mmd_control;
377+
378+ /*
379+ * a) To Register 13, write the Function field to 00 (address)
380+ * and DEVAD field to the device address value for the
381+ * desired MMD;
382+ */
383+ mmd_control.u16 = 0;
384+ mmd_control.s.function = MDIO_CLAUSE_45_ADDRESS;
385+ mmd_control.s.devad = device;
386+ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_CONTROL,
387+ mmd_control.u16);
388+
389+ /*
390+ * b) To Register 14, write the desired address value to the
391+ * MMD's address register;
392+ */
393+ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA,
394+ location);
395+
396+ /*
397+ * c) To Register 13, write the Function field to 01 (Data, no
398+ * post increment) and DEVAD field to the same device
399+ * address value for the desired MMD;
400+ */
401+ mmd_control.u16 = 0;
402+ mmd_control.s.function = MDIO_CLAUSE_45_READ;
403+ mmd_control.s.devad = device;
404+ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_CONTROL,
405+ mmd_control.u16);
406+
407+ /*
408+ * d) From Register 14, read the content of the MMD's selected
409+ * register.
410+ */
411+ return cvmx_mdio_read(bus_id, phy_id,
412+ CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA);
413+}
414+
415+/**
416+ * Perform an IEEE 802.3 clause 45 MII write using clause 22
417+ * operations. This function is used to write PHY registers
418+ * controlling auto negotiation.
419+ *
420+ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
421+ * support multiple busses.
422+ * @phy_id: The MII phy id
423+ * @device: MDIO Managable Device (MMD) id
424+ * @location: Register location to write
425+ * @val: Value to write
426+ *
427+ * Returns -1 on error
428+ * 0 on success
429+ */
430+static inline int cvmx_mdio_45_via_22_write(int bus_id, int phy_id, int device,
431+ int location, int val)
432+{
433+ union cvmx_mdio_phy_reg_mmd_control mmd_control;
434+
435+ /*
436+ * a) To Register 13, write the Function field to 00 (address)
437+ * and DEVAD field to the device address value for the
438+ * desired MMD;
439+ */
440+ mmd_control.u16 = 0;
441+ mmd_control.s.function = MDIO_CLAUSE_45_ADDRESS;
442+ mmd_control.s.devad = device;
443+ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_CONTROL,
444+ mmd_control.u16);
445+
446+ /*
447+ * b) To Register 14, write the desired address value to the
448+ * MMD's address register;
449+ */
450+ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA,
451+ location);
452+
453+ /*
454+ * c) To Register 13, write the Function field to 01 (Data, no
455+ * post increment) and DEVAD field to the same device
456+ * address value for the desired MMD;
457+ */
458+ mmd_control.u16 = 0;
459+ mmd_control.s.function = MDIO_CLAUSE_45_READ;
460+ mmd_control.s.devad = device;
461+ cvmx_mdio_write(bus_id, phy_id, CVMX_MDIO_PHY_REG_MMD_CONTROL,
462+ mmd_control.u16);
463+
464+ /*
465+ * d) To Register 14, write the content of the MMD's selected
466+ * register.
467+ */
468+ return cvmx_mdio_write(bus_id, phy_id,
469+ CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA, val);
470+
471+ return 0;
472+}
473+
474+/**
475+ * Perform an IEEE 802.3 clause 45 MII read. This function is used to read PHY
476+ * registers controlling auto negotiation.
477+ *
478+ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
479+ * support multiple busses.
480+ * @phy_id: The MII phy id
481+ * @device: MDIO Managable Device (MMD) id
482+ * @location: Register location to read
483+ *
484+ * Returns Result from the read or -1 on failure
485+ */
486+
487+static inline int cvmx_mdio_45_read(int bus_id, int phy_id, int device,
488+ int location)
489+{
490+ union cvmx_smix_cmd smi_cmd;
491+ union cvmx_smix_rd_dat smi_rd;
492+ union cvmx_smix_wr_dat smi_wr;
493+ int timeout = 1000;
494+
495+ smi_wr.u64 = 0;
496+ smi_wr.s.dat = location;
497+ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
498+
499+ smi_cmd.u64 = 0;
500+ smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS;
501+ smi_cmd.s.phy_adr = phy_id;
502+ smi_cmd.s.reg_adr = device;
503+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
504+
505+ do {
506+ cvmx_wait(1000);
507+ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
508+ } while (smi_wr.s.pending && --timeout);
509+ if (timeout <= 0)
510+ return -1;
511+
512+ smi_cmd.u64 = 0;
513+ smi_cmd.s.phy_op = MDIO_CLAUSE_45_READ;
514+ smi_cmd.s.phy_adr = phy_id;
515+ smi_cmd.s.reg_adr = device;
516+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
517+
518+ do {
519+ cvmx_wait(1000);
520+ smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id));
521+ } while (smi_rd.s.pending && timeout--);
522+
523+ if (0 == timeout)
524+ cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d "
525+ "device %2d register %2d TIME OUT\n",
526+ bus_id, phy_id, device, location);
527+
528+ if (smi_rd.s.val)
529+ return smi_rd.s.dat;
530+ else {
531+ cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d "
532+ "device %2d register %2d INVALID READ\n",
533+ bus_id, phy_id, device, location);
534+ return -1;
535+ }
536+}
537+
538+/**
539+ * Perform an IEEE 802.3 clause 45 MII write. This function is used to
540+ * write PHY registers controlling auto negotiation.
541+ *
542+ * @bus_id: MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
543+ * support multiple busses.
544+ * @phy_id: The MII phy id
545+ * @device: MDIO Managable Device (MMD) id
546+ * @location: Register location to write
547+ * @val: Value to write
548+ *
549+ * Returns -1 on error
550+ * 0 on success
551+ */
552+static inline int cvmx_mdio_45_write(int bus_id, int phy_id, int device,
553+ int location, int val)
554+{
555+ union cvmx_smix_cmd smi_cmd;
556+ union cvmx_smix_wr_dat smi_wr;
557+ int timeout = 1000;
558+
559+ smi_wr.u64 = 0;
560+ smi_wr.s.dat = location;
561+ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
562+
563+ smi_cmd.u64 = 0;
564+ smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS;
565+ smi_cmd.s.phy_adr = phy_id;
566+ smi_cmd.s.reg_adr = device;
567+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
568+
569+ do {
570+ cvmx_wait(1000);
571+ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
572+ } while (smi_wr.s.pending && --timeout);
573+ if (timeout <= 0)
574+ return -1;
575+
576+ smi_wr.u64 = 0;
577+ smi_wr.s.dat = val;
578+ cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
579+
580+ smi_cmd.u64 = 0;
581+ smi_cmd.s.phy_op = MDIO_CLAUSE_45_WRITE;
582+ smi_cmd.s.phy_adr = phy_id;
583+ smi_cmd.s.reg_adr = device;
584+ cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
585+
586+ do {
587+ cvmx_wait(1000);
588+ smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
589+ } while (smi_wr.s.pending && --timeout);
590+ if (timeout <= 0)
591+ return -1;
592+
593+ return 0;
594+}
595+
596+#endif
597--- a/drivers/net/Kconfig
598+++ b/drivers/net/Kconfig
599@@ -2035,6 +2035,14 @@ config ATL2
600       To compile this driver as a module, choose M here. The module
601       will be called atl2.
602 
603+config OCTEON_MGMT
604+ tristate "OCTEON Management port ethernet driver (CN5XXX)"
605+ depends on CPU_CAVIUM_OCTEON
606+ default y
607+ help
608+ This option enables the ethernet driver for the management port on
609+ CN52XX, CN57XX, CN56XX, CN55XX, and CN54XX chips.
610+
611 source "drivers/net/fs_enet/Kconfig"
612 
613 endif # NET_ETHERNET
614--- a/drivers/net/Makefile
615+++ b/drivers/net/Makefile
616@@ -234,6 +234,7 @@ pasemi_mac_driver-objs := pasemi_mac.o p
617 obj-$(CONFIG_MLX4_CORE) += mlx4/
618 obj-$(CONFIG_ENC28J60) += enc28j60.o
619 obj-$(CONFIG_ETHOC) += ethoc.o
620+obj-$(CONFIG_OCTEON_MGMT) += octeon/
621 
622 obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o
623 
624--- /dev/null
625+++ b/drivers/net/octeon/Makefile
626@@ -0,0 +1,11 @@
627+# Makefile for the Cavium OCTEON Ethernet drivers.
628+#
629+# This file is subject to the terms and conditions of the GNU General Public
630+# License. See the file "COPYING" in the main directory of this archive
631+# for more details.
632+#
633+# Copyright (C) 2008 Cavium Networks
634+
635+obj-$(CONFIG_OCTEON_MGMT) += octeon_mgmt.o
636+
637+octeon_mgmt-objs := octeon-mgmt-port.o cvmx-mgmt-port.o
638\ No newline at end of file
639--- /dev/null
640+++ b/drivers/net/octeon/cvmx-mgmt-port.c
641@@ -0,0 +1,818 @@
642+/***********************license start***************
643+ * Author: Cavium Networks
644+ *
645+ * Contact: support@caviumnetworks.com
646+ * This file is part of the OCTEON SDK
647+ *
648+ * Copyright (c) 2003-2008 Cavium Networks
649+ *
650+ * This file is free software; you can redistribute it and/or modify
651+ * it under the terms of the GNU General Public License, Version 2, as
652+ * published by the Free Software Foundation.
653+ *
654+ * This file is distributed in the hope that it will be useful, but
655+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
656+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
657+ * NONINFRINGEMENT. See the GNU General Public License for more
658+ * details.
659+ *
660+ * You should have received a copy of the GNU General Public License
661+ * along with this file; if not, write to the Free Software
662+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
663+ * or visit http://www.gnu.org/licenses/.
664+ *
665+ * This file may also be available under a different license from Cavium.
666+ * Contact Cavium Networks for more information
667+ ***********************license end**************************************/
668+
669+/**
670+ *
671+ * Support functions for managing the MII management port
672+ *
673+ */
674+
675+#include <asm/octeon/octeon.h>
676+#include <asm/octeon/cvmx-spinlock.h>
677+#include <asm/octeon/cvmx-bootmem.h>
678+#include <asm/octeon/cvmx-mdio.h>
679+
680+#include <asm/octeon/cvmx-mixx-defs.h>
681+#include <asm/octeon/cvmx-agl-defs.h>
682+
683+#include "cvmx-mgmt-port.h"
684+
685+#define CVMX_MGMT_PORT_NUM_PORTS 2
686+/* Number of TX ring buffer entries and buffers */
687+#define CVMX_MGMT_PORT_NUM_TX_BUFFERS 16
688+/* Number of RX ring buffer entries and buffers */
689+#define CVMX_MGMT_PORT_NUM_RX_BUFFERS 128
690+
691+#define CVMX_MGMT_PORT_TX_BUFFER_SIZE 12288
692+#define CVMX_MGMT_PORT_RX_BUFFER_SIZE 1536
693+
694+/**
695+ * Format of the TX/RX ring buffer entries
696+ */
697+union cvmx_mgmt_port_ring_entry {
698+ uint64_t u64;
699+ struct {
700+ uint64_t reserved_62_63:2;
701+ /* Length of the buffer/packet in bytes */
702+ uint64_t len:14;
703+ /* The RX error code */
704+ uint64_t code:8;
705+ /* Physical address of the buffer */
706+ uint64_t addr:40;
707+ } s;
708+};
709+
710+/**
711+ * Per port state required for each mgmt port
712+ */
713+struct cvmx_mgmt_port_state {
714+ /* Used for exclusive access to this structure */
715+ cvmx_spinlock_t lock;
716+ /* Where the next TX will write in the tx_ring and tx_buffers */
717+ int tx_write_index;
718+ /* Where the next RX will be in the rx_ring and rx_buffers */
719+ int rx_read_index;
720+ /* The SMI/MDIO PHY address */
721+ int phy_id;
722+ /* Our MAC address */
723+ uint64_t mac;
724+ union cvmx_mgmt_port_ring_entry tx_ring[CVMX_MGMT_PORT_NUM_TX_BUFFERS];
725+ union cvmx_mgmt_port_ring_entry rx_ring[CVMX_MGMT_PORT_NUM_RX_BUFFERS];
726+ char tx_buffers[CVMX_MGMT_PORT_NUM_TX_BUFFERS]
727+ [CVMX_MGMT_PORT_TX_BUFFER_SIZE];
728+ char rx_buffers[CVMX_MGMT_PORT_NUM_RX_BUFFERS]
729+ [CVMX_MGMT_PORT_RX_BUFFER_SIZE];
730+};
731+
732+/**
733+ * Pointers to each mgmt port's state
734+ */
735+struct cvmx_mgmt_port_state *cvmx_mgmt_port_state_ptr;
736+
737+/**
738+ * Return the number of management ports supported by this chip
739+ *
740+ * Returns Number of ports
741+ */
742+int __cvmx_mgmt_port_num_ports(void)
743+{
744+ if (OCTEON_IS_MODEL(OCTEON_CN56XX))
745+ return 1;
746+ else if (OCTEON_IS_MODEL(OCTEON_CN52XX))
747+ return 2;
748+ else
749+ return 0;
750+}
751+
752+/**
753+ * Called to initialize a management port for use. Multiple calls
754+ * to this function accross applications is safe.
755+ *
756+ * @port: Port to initialize
757+ *
758+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code
759+ */
760+enum cvmx_mgmt_port_result cvmx_mgmt_port_initialize(int port)
761+{
762+ char *alloc_name = "cvmx_mgmt_port";
763+ union cvmx_mixx_oring1 oring1;
764+ union cvmx_mixx_ctl mix_ctl;
765+
766+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports()))
767+ return CVMX_MGMT_PORT_INVALID_PARAM;
768+
769+ cvmx_mgmt_port_state_ptr =
770+ cvmx_bootmem_alloc_named(CVMX_MGMT_PORT_NUM_PORTS *
771+ sizeof(struct cvmx_mgmt_port_state), 128,
772+ alloc_name);
773+ if (cvmx_mgmt_port_state_ptr) {
774+ memset(cvmx_mgmt_port_state_ptr, 0,
775+ CVMX_MGMT_PORT_NUM_PORTS *
776+ sizeof(struct cvmx_mgmt_port_state));
777+ } else {
778+ struct cvmx_bootmem_named_block_desc *block_desc =
779+ cvmx_bootmem_find_named_block(alloc_name);
780+ if (block_desc)
781+ cvmx_mgmt_port_state_ptr =
782+ cvmx_phys_to_ptr(block_desc->base_addr);
783+ else {
784+ cvmx_dprintf("ERROR: cvmx_mgmt_port_initialize: "
785+ "Unable to get named block %s.\n",
786+ alloc_name);
787+ return CVMX_MGMT_PORT_NO_MEMORY;
788+ }
789+ }
790+
791+ /*
792+ * Reset the MIX block if the previous user had a different TX
793+ * ring size.
794+ */
795+ mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port));
796+ if (!mix_ctl.s.reset) {
797+ oring1.u64 = cvmx_read_csr(CVMX_MIXX_ORING1(port));
798+ if (oring1.s.osize != CVMX_MGMT_PORT_NUM_TX_BUFFERS) {
799+ mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port));
800+ mix_ctl.s.en = 0;
801+ cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64);
802+ do {
803+ mix_ctl.u64 =
804+ cvmx_read_csr(CVMX_MIXX_CTL(port));
805+ } while (mix_ctl.s.busy);
806+ mix_ctl.s.reset = 1;
807+ cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64);
808+ cvmx_read_csr(CVMX_MIXX_CTL(port));
809+ memset(cvmx_mgmt_port_state_ptr + port, 0,
810+ sizeof(struct cvmx_mgmt_port_state));
811+ }
812+ }
813+
814+ if (cvmx_mgmt_port_state_ptr[port].tx_ring[0].u64 == 0) {
815+ struct cvmx_mgmt_port_state *state =
816+ cvmx_mgmt_port_state_ptr + port;
817+ int i;
818+ union cvmx_mixx_bist mix_bist;
819+ union cvmx_agl_gmx_bist agl_gmx_bist;
820+ union cvmx_mixx_oring1 oring1;
821+ union cvmx_mixx_iring1 iring1;
822+ union cvmx_mixx_ctl mix_ctl;
823+
824+ /* Make sure BIST passed */
825+ mix_bist.u64 = cvmx_read_csr(CVMX_MIXX_BIST(port));
826+ if (mix_bist.u64)
827+ cvmx_dprintf("WARNING: cvmx_mgmt_port_initialize: "
828+ "Managment port MIX failed BIST "
829+ "(0x%016llx)\n",
830+ (unsigned long long)mix_bist.u64);
831+
832+ agl_gmx_bist.u64 = cvmx_read_csr(CVMX_AGL_GMX_BIST);
833+ if (agl_gmx_bist.u64)
834+ cvmx_dprintf("WARNING: cvmx_mgmt_port_initialize: "
835+ "Managment port AGL failed BIST "
836+ "(0x%016llx)\n",
837+ (unsigned long long)agl_gmx_bist.u64);
838+
839+ /* Clear all state information */
840+ memset(state, 0, sizeof(*state));
841+
842+ /* Take the control logic out of reset */
843+ mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port));
844+ mix_ctl.s.reset = 0;
845+ cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64);
846+
847+ /* Set the PHY address */
848+ if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM)
849+ state->phy_id = -1;
850+ else
851+ /* Will need to be change to match the board */
852+ state->phy_id = port;
853+
854+ /* Create a default MAC address */
855+ state->mac = 0x000000dead000000ull;
856+ state->mac += 0xffffff & CAST64(state);
857+
858+ /* Setup the TX ring */
859+ for (i = 0; i < CVMX_MGMT_PORT_NUM_TX_BUFFERS; i++) {
860+ state->tx_ring[i].s.len = CVMX_MGMT_PORT_TX_BUFFER_SIZE;
861+ state->tx_ring[i].s.addr =
862+ cvmx_ptr_to_phys(state->tx_buffers[i]);
863+ }
864+
865+ /* Tell the HW where the TX ring is */
866+ oring1.u64 = 0;
867+ oring1.s.obase = cvmx_ptr_to_phys(state->tx_ring) >> 3;
868+ oring1.s.osize = CVMX_MGMT_PORT_NUM_TX_BUFFERS;
869+ CVMX_SYNCWS;
870+ cvmx_write_csr(CVMX_MIXX_ORING1(port), oring1.u64);
871+
872+ /* Setup the RX ring */
873+ for (i = 0; i < CVMX_MGMT_PORT_NUM_RX_BUFFERS; i++) {
874+ /* This size is -8 due to an errata for CN56XX pass 1 */
875+ state->rx_ring[i].s.len =
876+ CVMX_MGMT_PORT_RX_BUFFER_SIZE - 8;
877+ state->rx_ring[i].s.addr =
878+ cvmx_ptr_to_phys(state->rx_buffers[i]);
879+ }
880+
881+ /* Tell the HW where the RX ring is */
882+ iring1.u64 = 0;
883+ iring1.s.ibase = cvmx_ptr_to_phys(state->rx_ring) >> 3;
884+ iring1.s.isize = CVMX_MGMT_PORT_NUM_RX_BUFFERS;
885+ CVMX_SYNCWS;
886+ cvmx_write_csr(CVMX_MIXX_IRING1(port), iring1.u64);
887+ cvmx_write_csr(CVMX_MIXX_IRING2(port),
888+ CVMX_MGMT_PORT_NUM_RX_BUFFERS);
889+
890+ /* Disable the external input/output */
891+ cvmx_mgmt_port_disable(port);
892+
893+ /* Set the MAC address filtering up */
894+ cvmx_mgmt_port_set_mac(port, state->mac);
895+
896+ /*
897+ * Set the default max size to an MTU of 1500 with L2
898+ * and VLAN.
899+ */
900+ cvmx_mgmt_port_set_max_packet_size(port, 1518);
901+
902+ /*
903+ * Enable the port HW. Packets are not allowed until
904+ * cvmx_mgmt_port_enable() is called.
905+ */
906+ mix_ctl.u64 = 0;
907+ /* Strip the ending CRC */
908+ mix_ctl.s.crc_strip = 1;
909+ /* Enable the port */
910+ mix_ctl.s.en = 1;
911+ /* Arbitration mode */
912+ mix_ctl.s.nbtarb = 0;
913+ /* MII CB-request FIFO programmable high watermark */
914+ mix_ctl.s.mrq_hwm = 1;
915+ cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64);
916+
917+ if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)
918+ || OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
919+ /*
920+ * Force compensation values, as they are not
921+ * determined properly by HW.
922+ */
923+ union cvmx_agl_gmx_drv_ctl drv_ctl;
924+
925+ drv_ctl.u64 = cvmx_read_csr(CVMX_AGL_GMX_DRV_CTL);
926+ if (port) {
927+ drv_ctl.s.byp_en1 = 1;
928+ drv_ctl.s.nctl1 = 6;
929+ drv_ctl.s.pctl1 = 6;
930+ } else {
931+ drv_ctl.s.byp_en = 1;
932+ drv_ctl.s.nctl = 6;
933+ drv_ctl.s.pctl = 6;
934+ }
935+ cvmx_write_csr(CVMX_AGL_GMX_DRV_CTL, drv_ctl.u64);
936+ }
937+ }
938+ return CVMX_MGMT_PORT_SUCCESS;
939+}
940+
941+/**
942+ * Shutdown a management port. This currently disables packet IO
943+ * but leaves all hardware and buffers. Another application can then
944+ * call initialize() without redoing the hardware setup.
945+ *
946+ * @port: Management port
947+ *
948+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code
949+ */
950+enum cvmx_mgmt_port_result cvmx_mgmt_port_shutdown(int port)
951+{
952+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports()))
953+ return CVMX_MGMT_PORT_INVALID_PARAM;
954+
955+ /* Stop packets from comming in */
956+ cvmx_mgmt_port_disable(port);
957+
958+ /*
959+ * We don't free any memory so the next intialize can reuse
960+ * the HW setup.
961+ */
962+ return CVMX_MGMT_PORT_SUCCESS;
963+}
964+
965+/**
966+ * Enable packet IO on a management port
967+ *
968+ * @port: Management port
969+ *
970+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code
971+ */
972+enum cvmx_mgmt_port_result cvmx_mgmt_port_enable(int port)
973+{
974+ struct cvmx_mgmt_port_state *state;
975+ union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx;
976+ union cvmx_agl_gmx_inf_mode agl_gmx_inf_mode;
977+ union cvmx_agl_gmx_rxx_frm_ctl rxx_frm_ctl;
978+
979+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports()))
980+ return CVMX_MGMT_PORT_INVALID_PARAM;
981+
982+ state = cvmx_mgmt_port_state_ptr + port;
983+
984+ cvmx_spinlock_lock(&state->lock);
985+
986+ rxx_frm_ctl.u64 = 0;
987+ rxx_frm_ctl.s.pre_align = 1;
988+ /*
989+ * When set, disables the length check for non-min sized pkts
990+ * with padding in the client data.
991+ */
992+ rxx_frm_ctl.s.pad_len = 1;
993+ /* When set, disables the length check for VLAN pkts */
994+ rxx_frm_ctl.s.vlan_len = 1;
995+ /* When set, PREAMBLE checking is less strict */
996+ rxx_frm_ctl.s.pre_free = 1;
997+ /* Control Pause Frames can match station SMAC */
998+ rxx_frm_ctl.s.ctl_smac = 0;
999+ /* Control Pause Frames can match globally assign Multicast address */
1000+ rxx_frm_ctl.s.ctl_mcst = 1;
1001+ /* Forward pause information to TX block */
1002+ rxx_frm_ctl.s.ctl_bck = 1;
1003+ /* Drop Control Pause Frames */
1004+ rxx_frm_ctl.s.ctl_drp = 1;
1005+ /* Strip off the preamble */
1006+ rxx_frm_ctl.s.pre_strp = 1;
1007+ /*
1008+ * This port is configured to send PREAMBLE+SFD to begin every
1009+ * frame. GMX checks that the PREAMBLE is sent correctly.
1010+ */
1011+ rxx_frm_ctl.s.pre_chk = 1;
1012+ cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_CTL(port), rxx_frm_ctl.u64);
1013+
1014+ /* Enable the AGL block */
1015+ agl_gmx_inf_mode.u64 = 0;
1016+ agl_gmx_inf_mode.s.en = 1;
1017+ cvmx_write_csr(CVMX_AGL_GMX_INF_MODE, agl_gmx_inf_mode.u64);
1018+
1019+ /* Configure the port duplex and enables */
1020+ agl_gmx_prtx.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
1021+ agl_gmx_prtx.s.tx_en = 1;
1022+ agl_gmx_prtx.s.rx_en = 1;
1023+ if (cvmx_mgmt_port_get_link(port) < 0)
1024+ agl_gmx_prtx.s.duplex = 0;
1025+ else
1026+ agl_gmx_prtx.s.duplex = 1;
1027+ agl_gmx_prtx.s.en = 1;
1028+ cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64);
1029+
1030+ cvmx_spinlock_unlock(&state->lock);
1031+ return CVMX_MGMT_PORT_SUCCESS;
1032+}
1033+
1034+/**
1035+ * Disable packet IO on a management port
1036+ *
1037+ * @port: Management port
1038+ *
1039+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code
1040+ */
1041+enum cvmx_mgmt_port_result cvmx_mgmt_port_disable(int port)
1042+{
1043+ struct cvmx_mgmt_port_state *state;
1044+ union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx;
1045+
1046+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports()))
1047+ return CVMX_MGMT_PORT_INVALID_PARAM;
1048+
1049+ state = cvmx_mgmt_port_state_ptr + port;
1050+
1051+ cvmx_spinlock_lock(&state->lock);
1052+
1053+ agl_gmx_prtx.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
1054+ agl_gmx_prtx.s.en = 0;
1055+ cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64);
1056+
1057+ cvmx_spinlock_unlock(&state->lock);
1058+ return CVMX_MGMT_PORT_SUCCESS;
1059+}
1060+
1061+/**
1062+ * Send a packet out the management port. The packet is copied so
1063+ * the input buffer isn't used after this call.
1064+ *
1065+ * @port: Management port
1066+ * @packet_len: Length of the packet to send. It does not include the final CRC
1067+ * @buffer: Packet data
1068+ *
1069+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code
1070+ */
1071+enum cvmx_mgmt_port_result cvmx_mgmt_port_send(int port, int packet_len,
1072+ void *buffer)
1073+{
1074+ struct cvmx_mgmt_port_state *state;
1075+ union cvmx_mixx_oring2 mix_oring2;
1076+
1077+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports()))
1078+ return CVMX_MGMT_PORT_INVALID_PARAM;
1079+
1080+ /* Max sure the packet size is valid */
1081+ if ((packet_len < 1) || (packet_len > CVMX_MGMT_PORT_TX_BUFFER_SIZE))
1082+ return CVMX_MGMT_PORT_INVALID_PARAM;
1083+
1084+ if (buffer == NULL)
1085+ return CVMX_MGMT_PORT_INVALID_PARAM;
1086+
1087+ state = cvmx_mgmt_port_state_ptr + port;
1088+
1089+ cvmx_spinlock_lock(&state->lock);
1090+
1091+ mix_oring2.u64 = cvmx_read_csr(CVMX_MIXX_ORING2(port));
1092+ if (mix_oring2.s.odbell >= CVMX_MGMT_PORT_NUM_TX_BUFFERS - 1) {
1093+ /* No room for another packet */
1094+ cvmx_spinlock_unlock(&state->lock);
1095+ return CVMX_MGMT_PORT_NO_MEMORY;
1096+ } else {
1097+ /* Copy the packet into the output buffer */
1098+ memcpy(state->tx_buffers[state->tx_write_index], buffer,
1099+ packet_len);
1100+ /* Insert the source MAC */
1101+ memcpy(state->tx_buffers[state->tx_write_index] + 6,
1102+ ((char *)&state->mac) + 2, 6);
1103+ /* Update the TX ring buffer entry size */
1104+ state->tx_ring[state->tx_write_index].s.len = packet_len;
1105+ /* Increment our TX index */
1106+ state->tx_write_index =
1107+ (state->tx_write_index + 1) % CVMX_MGMT_PORT_NUM_TX_BUFFERS;
1108+ /* Ring the doorbell, send ing the packet */
1109+ CVMX_SYNCWS;
1110+ cvmx_write_csr(CVMX_MIXX_ORING2(port), 1);
1111+ if (cvmx_read_csr(CVMX_MIXX_ORCNT(port)))
1112+ cvmx_write_csr(CVMX_MIXX_ORCNT(port),
1113+ cvmx_read_csr(CVMX_MIXX_ORCNT(port)));
1114+
1115+ cvmx_spinlock_unlock(&state->lock);
1116+ return CVMX_MGMT_PORT_SUCCESS;
1117+ }
1118+}
1119+
1120+/**
1121+ * Receive a packet from the management port.
1122+ *
1123+ * @port: Management port
1124+ * @buffer_len: Size of the buffer to receive the packet into
1125+ * @buffer: Buffer to receive the packet into
1126+ *
1127+ * Returns The size of the packet, or a negative erorr code on failure. Zero
1128+ * means that no packets were available.
1129+ */
1130+int cvmx_mgmt_port_receive(int port, int buffer_len, void *buffer)
1131+{
1132+ union cvmx_mixx_ircnt mix_ircnt;
1133+ struct cvmx_mgmt_port_state *state;
1134+ int result;
1135+
1136+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports()))
1137+ return CVMX_MGMT_PORT_INVALID_PARAM;
1138+
1139+ /* Max sure the buffer size is valid */
1140+ if (buffer_len < 1)
1141+ return CVMX_MGMT_PORT_INVALID_PARAM;
1142+
1143+ if (buffer == NULL)
1144+ return CVMX_MGMT_PORT_INVALID_PARAM;
1145+
1146+ state = cvmx_mgmt_port_state_ptr + port;
1147+
1148+ cvmx_spinlock_lock(&state->lock);
1149+
1150+ /* Find out how many RX packets are pending */
1151+ mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port));
1152+ if (mix_ircnt.s.ircnt) {
1153+ void *source = state->rx_buffers[state->rx_read_index];
1154+ uint64_t *zero_check = source;
1155+ /*
1156+ * CN56XX pass 1 has an errata where packets might
1157+ * start 8 bytes into the buffer instead of at their
1158+ * correct location. If the first 8 bytes is zero we
1159+ * assume this has happened.
1160+ */
1161+ if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)
1162+ && (*zero_check == 0))
1163+ source += 8;
1164+ /* Start off with zero bytes received */
1165+ result = 0;
1166+ /*
1167+ * While the completion code signals more data, copy
1168+ * the buffers into the user's data.
1169+ */
1170+ while (state->rx_ring[state->rx_read_index].s.code == 16) {
1171+ /* Only copy what will fit in the user's buffer */
1172+ int length = state->rx_ring[state->rx_read_index].s.len;
1173+ if (length > buffer_len)
1174+ length = buffer_len;
1175+ memcpy(buffer, source, length);
1176+ /*
1177+ * Reduce the size of the buffer to the
1178+ * remaining space. If we run out we will
1179+ * signal an error when the code 15 buffer
1180+ * doesn't fit.
1181+ */
1182+ buffer += length;
1183+ buffer_len -= length;
1184+ result += length;
1185+ /*
1186+ * Update this buffer for reuse in future
1187+ * receives. This size is -8 due to an errata
1188+ * for CN56XX pass 1.
1189+ */
1190+ state->rx_ring[state->rx_read_index].s.code = 0;
1191+ state->rx_ring[state->rx_read_index].s.len =
1192+ CVMX_MGMT_PORT_RX_BUFFER_SIZE - 8;
1193+ state->rx_read_index =
1194+ (state->rx_read_index +
1195+ 1) % CVMX_MGMT_PORT_NUM_RX_BUFFERS;
1196+ /*
1197+ * Zero the beginning of the buffer for use by
1198+ * the errata check.
1199+ */
1200+ *zero_check = 0;
1201+ CVMX_SYNCWS;
1202+ /* Increment the number of RX buffers */
1203+ cvmx_write_csr(CVMX_MIXX_IRING2(port), 1);
1204+ source = state->rx_buffers[state->rx_read_index];
1205+ zero_check = source;
1206+ }
1207+
1208+ /* Check for the final good completion code */
1209+ if (state->rx_ring[state->rx_read_index].s.code == 15) {
1210+ if (buffer_len >=
1211+ state->rx_ring[state->rx_read_index].s.len) {
1212+ int length =
1213+ state->rx_ring[state->rx_read_index].s.len;
1214+ memcpy(buffer, source, length);
1215+ result += length;
1216+ } else {
1217+ /* Not enough room for the packet */
1218+ cvmx_dprintf("ERROR: cvmx_mgmt_port_receive: "
1219+ "Packet (%d) larger than "
1220+ "supplied buffer (%d)\n",
1221+ state->rx_ring[state->rx_read_index].s.len,
1222+ buffer_len);
1223+ result = CVMX_MGMT_PORT_NO_MEMORY;
1224+ }
1225+ } else {
1226+ union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx;
1227+ cvmx_dprintf("ERROR: cvmx_mgmt_port_receive: Receive "
1228+ "error code %d. Packet dropped(Len %d)\n",
1229+ state->rx_ring[state->rx_read_index].s.code,
1230+ state->rx_ring[state->rx_read_index].s.len +
1231+ result);
1232+ result = -state->rx_ring[state->rx_read_index].s.code;
1233+
1234+ /* Check to see if we need to change the duplex. */
1235+ agl_gmx_prtx.u64 =
1236+ cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
1237+ if (cvmx_mgmt_port_get_link(port) < 0)
1238+ agl_gmx_prtx.s.duplex = 0;
1239+ else
1240+ agl_gmx_prtx.s.duplex = 1;
1241+ cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port),
1242+ agl_gmx_prtx.u64);
1243+ }
1244+
1245+ /*
1246+ * Clean out the ring buffer entry. This size is -8
1247+ * due to an errata for CN56XX pass 1.
1248+ */
1249+ state->rx_ring[state->rx_read_index].s.code = 0;
1250+ state->rx_ring[state->rx_read_index].s.len =
1251+ CVMX_MGMT_PORT_RX_BUFFER_SIZE - 8;
1252+ state->rx_read_index =
1253+ (state->rx_read_index + 1) % CVMX_MGMT_PORT_NUM_RX_BUFFERS;
1254+ /*
1255+ * Zero the beginning of the buffer for use by the
1256+ * errata check.
1257+ */
1258+ *zero_check = 0;
1259+ CVMX_SYNCWS;
1260+ /* Increment the number of RX buffers */
1261+ cvmx_write_csr(CVMX_MIXX_IRING2(port), 1);
1262+ /* Decrement the pending RX count */
1263+ cvmx_write_csr(CVMX_MIXX_IRCNT(port), 1);
1264+ } else {
1265+ /* No packets available */
1266+ result = 0;
1267+ }
1268+ cvmx_spinlock_unlock(&state->lock);
1269+ return result;
1270+}
1271+
1272+/**
1273+ * Get the management port link status:
1274+ * 100 = 100Mbps, full duplex
1275+ * 10 = 10Mbps, full duplex
1276+ * 0 = Link down
1277+ * -10 = 10Mpbs, half duplex
1278+ * -100 = 100Mbps, half duplex
1279+ *
1280+ * @port: Management port
1281+ *
1282+ * Returns
1283+ */
1284+int cvmx_mgmt_port_get_link(int port)
1285+{
1286+ struct cvmx_mgmt_port_state *state;
1287+ int phy_status;
1288+ int duplex;
1289+
1290+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports()))
1291+ return CVMX_MGMT_PORT_INVALID_PARAM;
1292+
1293+ state = cvmx_mgmt_port_state_ptr + port;
1294+
1295+ /* Assume 100Mbps if we don't know the PHY address */
1296+ if (state->phy_id == -1)
1297+ return 100;
1298+
1299+ /* Read the PHY state */
1300+ phy_status =
1301+ cvmx_mdio_read(state->phy_id >> 8, state->phy_id & 0xff, 17);
1302+
1303+ /* Only return a link if the PHY has finished auto negotiation
1304+ and set the resolved bit (bit 11) */
1305+ if (!(phy_status & (1 << 11)))
1306+ return 0;
1307+
1308+ /* Create multiple factor to represent duplex */
1309+ if ((phy_status >> 13) & 1)
1310+ duplex = 1;
1311+ else
1312+ duplex = -1;
1313+
1314+ /* Speed is encoded on bits 15-14 */
1315+ switch ((phy_status >> 14) & 3) {
1316+ case 0: /* 10 Mbps */
1317+ return 10 * duplex;
1318+ case 1: /* 100 Mbps */
1319+ return 100 * duplex;
1320+ default:
1321+ return 0;
1322+ }
1323+}
1324+
1325+/**
1326+ * Set the MAC address for a management port
1327+ *
1328+ * @port: Management port
1329+ * @mac: New MAC address. The lower 6 bytes are used.
1330+ *
1331+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code
1332+ */
1333+enum cvmx_mgmt_port_result cvmx_mgmt_port_set_mac(int port, uint64_t mac)
1334+{
1335+ struct cvmx_mgmt_port_state *state;
1336+ union cvmx_agl_gmx_rxx_adr_ctl agl_gmx_rxx_adr_ctl;
1337+
1338+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports()))
1339+ return CVMX_MGMT_PORT_INVALID_PARAM;
1340+
1341+ state = cvmx_mgmt_port_state_ptr + port;
1342+
1343+ cvmx_spinlock_lock(&state->lock);
1344+
1345+ agl_gmx_rxx_adr_ctl.u64 = 0;
1346+ /* Only accept matching MAC addresses */
1347+ agl_gmx_rxx_adr_ctl.s.cam_mode = 1;
1348+ /* Drop multicast */
1349+ agl_gmx_rxx_adr_ctl.s.mcst = 0;
1350+ /* Allow broadcast */
1351+ agl_gmx_rxx_adr_ctl.s.bcst = 1;
1352+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CTL(port), agl_gmx_rxx_adr_ctl.u64);
1353+
1354+ /* Only using one of the CAMs */
1355+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM0(port), (mac >> 40) & 0xff);
1356+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM1(port), (mac >> 32) & 0xff);
1357+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM2(port), (mac >> 24) & 0xff);
1358+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM3(port), (mac >> 16) & 0xff);
1359+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM4(port), (mac >> 8) & 0xff);
1360+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM5(port), (mac >> 0) & 0xff);
1361+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM_EN(port), 1);
1362+ state->mac = mac;
1363+
1364+ cvmx_spinlock_unlock(&state->lock);
1365+ return CVMX_MGMT_PORT_SUCCESS;
1366+}
1367+
1368+/**
1369+ * Get the MAC address for a management port
1370+ *
1371+ * @port: Management port
1372+ *
1373+ * Returns MAC address
1374+ */
1375+uint64_t cvmx_mgmt_port_get_mac(int port)
1376+{
1377+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports()))
1378+ return CVMX_MGMT_PORT_INVALID_PARAM;
1379+
1380+ return cvmx_mgmt_port_state_ptr[port].mac;
1381+}
1382+
1383+/**
1384+ * Set the multicast list.
1385+ *
1386+ * @port: Management port
1387+ * @flags: Interface flags
1388+ *
1389+ * Returns
1390+ */
1391+void cvmx_mgmt_port_set_multicast_list(int port, int flags)
1392+{
1393+ struct cvmx_mgmt_port_state *state;
1394+ union cvmx_agl_gmx_rxx_adr_ctl agl_gmx_rxx_adr_ctl;
1395+
1396+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports()))
1397+ return;
1398+
1399+ state = cvmx_mgmt_port_state_ptr + port;
1400+
1401+ cvmx_spinlock_lock(&state->lock);
1402+
1403+ agl_gmx_rxx_adr_ctl.u64 = cvmx_read_csr(CVMX_AGL_GMX_RXX_ADR_CTL(port));
1404+
1405+ /* Allow broadcast MAC addresses */
1406+ if (!agl_gmx_rxx_adr_ctl.s.bcst)
1407+ agl_gmx_rxx_adr_ctl.s.bcst = 1;
1408+
1409+ if ((flags & CVMX_IFF_ALLMULTI) || (flags & CVMX_IFF_PROMISC))
1410+ /* Force accept multicast packets */
1411+ agl_gmx_rxx_adr_ctl.s.mcst = 2;
1412+ else
1413+ /* Force reject multicast packets */
1414+ agl_gmx_rxx_adr_ctl.s.mcst = 1;
1415+
1416+ if (flags & CVMX_IFF_PROMISC)
1417+ /*
1418+ * Reject matches if promisc. Since CAM is shut off,
1419+ * should accept everything.
1420+ */
1421+ agl_gmx_rxx_adr_ctl.s.cam_mode = 0;
1422+ else
1423+ /* Filter packets based on the CAM */
1424+ agl_gmx_rxx_adr_ctl.s.cam_mode = 1;
1425+
1426+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CTL(port), agl_gmx_rxx_adr_ctl.u64);
1427+
1428+ if (flags & CVMX_IFF_PROMISC)
1429+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM_EN(port), 0);
1430+ else
1431+ cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM_EN(port), 1);
1432+
1433+ cvmx_spinlock_unlock(&state->lock);
1434+}
1435+
1436+/**
1437+ * Set the maximum packet allowed in. Size is specified
1438+ * including L2 but without FCS. A normal MTU would corespond
1439+ * to 1514 assuming the standard 14 byte L2 header.
1440+ *
1441+ * @port: Management port
1442+ * @size_without_fcs:
1443+ * Size in bytes without FCS
1444+ */
1445+void cvmx_mgmt_port_set_max_packet_size(int port, int size_without_fcs)
1446+{
1447+ struct cvmx_mgmt_port_state *state;
1448+
1449+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports()))
1450+ return;
1451+
1452+ state = cvmx_mgmt_port_state_ptr + port;
1453+
1454+ cvmx_spinlock_lock(&state->lock);
1455+ cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_MAX(port), size_without_fcs);
1456+ cvmx_write_csr(CVMX_AGL_GMX_RXX_JABBER(port),
1457+ (size_without_fcs + 7) & 0xfff8);
1458+ cvmx_spinlock_unlock(&state->lock);
1459+}
1460--- /dev/null
1461+++ b/drivers/net/octeon/cvmx-mgmt-port.h
1462@@ -0,0 +1,168 @@
1463+/***********************license start***************
1464+ * Author: Cavium Networks
1465+ *
1466+ * Contact: support@caviumnetworks.com
1467+ * This file is part of the OCTEON SDK
1468+ *
1469+ * Copyright (c) 2003-2008 Cavium Networks
1470+ *
1471+ * This file is free software; you can redistribute it and/or modify
1472+ * it under the terms of the GNU General Public License, Version 2, as
1473+ * published by the Free Software Foundation.
1474+ *
1475+ * This file is distributed in the hope that it will be useful, but
1476+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
1477+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
1478+ * NONINFRINGEMENT. See the GNU General Public License for more
1479+ * details.
1480+ *
1481+ * You should have received a copy of the GNU General Public License
1482+ * along with this file; if not, write to the Free Software
1483+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1484+ * or visit http://www.gnu.org/licenses/.
1485+ *
1486+ * This file may also be available under a different license from Cavium.
1487+ * Contact Cavium Networks for more information
1488+ ***********************license end**************************************/
1489+
1490+/**
1491+ *
1492+ * Support functions for managing the MII management port
1493+ *
1494+ */
1495+
1496+#ifndef __CVMX_MGMT_PORT_H__
1497+#define __CVMX_MGMT_PORT_H__
1498+
1499+enum cvmx_mgmt_port_result {
1500+ CVMX_MGMT_PORT_SUCCESS = 0,
1501+ CVMX_MGMT_PORT_NO_MEMORY = -1,
1502+ CVMX_MGMT_PORT_INVALID_PARAM = -2,
1503+};
1504+
1505+/* Enumeration of Net Device interface flags. */
1506+enum cvmx_mgmt_port_netdevice_flags {
1507+ CVMX_IFF_PROMISC = 0x100, /* receive all packets */
1508+ CVMX_IFF_ALLMULTI = 0x200, /* receive all multicast packets */
1509+};
1510+
1511+/**
1512+ * Called to initialize a management port for use. Multiple calls
1513+ * to this function accross applications is safe.
1514+ *
1515+ * @port: Port to initialize
1516+ *
1517+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code
1518+ */
1519+extern enum cvmx_mgmt_port_result cvmx_mgmt_port_initialize(int port);
1520+
1521+/**
1522+ * Shutdown a management port. This currently disables packet IO
1523+ * but leaves all hardware and buffers. Another application can then
1524+ * call initialize() without redoing the hardware setup.
1525+ *
1526+ * @port: Management port
1527+ *
1528+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code
1529+ */
1530+extern enum cvmx_mgmt_port_result cvmx_mgmt_port_shutdown(int port);
1531+
1532+/**
1533+ * Enable packet IO on a management port
1534+ *
1535+ * @port: Management port
1536+ *
1537+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code
1538+ */
1539+extern enum cvmx_mgmt_port_result cvmx_mgmt_port_enable(int port);
1540+
1541+/**
1542+ * Disable packet IO on a management port
1543+ *
1544+ * @port: Management port
1545+ *
1546+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code
1547+ */
1548+extern enum cvmx_mgmt_port_result cvmx_mgmt_port_disable(int port);
1549+
1550+/**
1551+ * Send a packet out the management port. The packet is copied so
1552+ * the input buffer isn't used after this call.
1553+ *
1554+ * @port: Management port
1555+ * @packet_len: Length of the packet to send. It does not include the final CRC
1556+ * @buffer: Packet data
1557+ *
1558+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code
1559+ */
1560+extern enum cvmx_mgmt_port_result cvmx_mgmt_port_send(int port, int packet_len,
1561+ void *buffer);
1562+
1563+/**
1564+ * Receive a packet from the management port.
1565+ *
1566+ * @port: Management port
1567+ * @buffer_len: Size of the buffer to receive the packet into
1568+ * @buffer: Buffer to receive the packet into
1569+ *
1570+ * Returns The size of the packet, or a negative erorr code on failure. Zero
1571+ * means that no packets were available.
1572+ */
1573+extern int cvmx_mgmt_port_receive(int port, int buffer_len, void *buffer);
1574+
1575+/**
1576+ * Get the management port link status:
1577+ * 100 = 100Mbps, full duplex
1578+ * 10 = 10Mbps, full duplex
1579+ * 0 = Link down
1580+ * -10 = 10Mpbs, half duplex
1581+ * -100 = 100Mbps, half duplex
1582+ *
1583+ * @port: Management port
1584+ *
1585+ * Returns
1586+ */
1587+extern int cvmx_mgmt_port_get_link(int port);
1588+
1589+/**
1590+ * Set the MAC address for a management port
1591+ *
1592+ * @port: Management port
1593+ * @mac: New MAC address. The lower 6 bytes are used.
1594+ *
1595+ * Returns CVMX_MGMT_PORT_SUCCESS or an error code
1596+ */
1597+extern enum cvmx_mgmt_port_result cvmx_mgmt_port_set_mac(int port,
1598+ uint64_t mac);
1599+
1600+/**
1601+ * Get the MAC address for a management port
1602+ *
1603+ * @port: Management port
1604+ *
1605+ * Returns MAC address
1606+ */
1607+extern uint64_t cvmx_mgmt_port_get_mac(int port);
1608+
1609+/**
1610+ * Set the multicast list.
1611+ *
1612+ * @port: Management port
1613+ * @flags: Interface flags
1614+ *
1615+ * Returns
1616+ */
1617+extern void cvmx_mgmt_port_set_multicast_list(int port, int flags);
1618+
1619+/**
1620+ * Set the maximum packet allowed in. Size is specified
1621+ * including L2 but without FCS. A normal MTU would corespond
1622+ * to 1514 assuming the standard 14 byte L2 header.
1623+ *
1624+ * @port: Management port
1625+ * @size_without_crc:
1626+ * Size in bytes without FCS
1627+ */
1628+extern void cvmx_mgmt_port_set_max_packet_size(int port, int size_without_fcs);
1629+
1630+#endif /* __CVMX_MGMT_PORT_H__ */
1631--- /dev/null
1632+++ b/drivers/net/octeon/octeon-mgmt-port.c
1633@@ -0,0 +1,389 @@
1634+/*
1635+ * Octeon Management Port Ethernet Driver
1636+ *
1637+ * This file is subject to the terms and conditions of the GNU General Public
1638+ * License. See the file "COPYING" in the main directory of this archive
1639+ * for more details.
1640+ *
1641+ * Copyright (C) 2007, 2008 Cavium Networks
1642+ */
1643+#include <linux/module.h>
1644+#include <linux/kernel.h>
1645+#include <linux/netdevice.h>
1646+#include <linux/etherdevice.h>
1647+#include <linux/ip.h>
1648+#include <linux/string.h>
1649+#include <linux/delay.h>
1650+
1651+#include <asm/octeon/octeon.h>
1652+#include <asm/octeon/cvmx-mixx-defs.h>
1653+#include <asm/octeon/cvmx-agl-defs.h>
1654+
1655+#include "cvmx-mgmt-port.h"
1656+
1657+static struct net_device *global_dev[2] = { NULL, NULL };
1658+
1659+#define DEBUGPRINT(format, ...) do {if (printk_ratelimit()) \
1660+ printk(format, ##__VA_ARGS__); \
1661+ } while (0)
1662+
1663+/**
1664+ * This is the definition of the Ethernet driver's private
1665+ * driver state stored in dev->priv.
1666+ */
1667+struct device_private {
1668+ int port;
1669+ struct net_device_stats stats; /* Device statistics */
1670+};
1671+
1672+
1673+/**
1674+ * Packet transmit
1675+ *
1676+ * @param skb Packet to send
1677+ * @param dev Device info structure
1678+ * @return Always returns zero
1679+ */
1680+static int packet_transmit(struct sk_buff *skb, struct net_device *dev)
1681+{
1682+ uint64_t flags;
1683+ struct device_private *priv = netdev_priv(dev);
1684+ enum cvmx_mgmt_port_result result;
1685+ local_irq_save(flags);
1686+ result = cvmx_mgmt_port_send(priv->port, skb->len, skb->data);
1687+ local_irq_restore(flags);
1688+ if (result == CVMX_MGMT_PORT_SUCCESS) {
1689+ priv->stats.tx_packets++;
1690+ priv->stats.tx_bytes += skb->len;
1691+ } else {
1692+ /* DEBUGPRINT("ERROR: cvmx_mgmt_port_send() failed with %d\n",
1693+ result);
1694+ */
1695+ priv->stats.tx_dropped++;
1696+ }
1697+ dev_kfree_skb(skb);
1698+ return 0;
1699+}
1700+
1701+
1702+/**
1703+ * Interrupt handler. The interrupt occurs whenever the POW
1704+ * transitions from 0->1 packets in our group.
1705+ *
1706+ * @param cpl
1707+ * @param dev_id
1708+ * @param regs
1709+ * @return
1710+ */
1711+static irqreturn_t do_interrupt(int cpl, void *dev_id)
1712+{
1713+ uint64_t flags;
1714+ struct sk_buff *skb;
1715+ int result;
1716+ char packet[2048];
1717+ struct net_device *dev = (struct net_device *) dev_id;
1718+ struct device_private *priv = netdev_priv(dev);
1719+
1720+ do {
1721+ local_irq_save(flags);
1722+ result = cvmx_mgmt_port_receive(priv->port, sizeof(packet),
1723+ packet);
1724+ local_irq_restore(flags);
1725+
1726+ /* Silently drop packets if we aren't up */
1727+ if ((dev->flags & IFF_UP) == 0)
1728+ continue;
1729+
1730+ if (result > 0) {
1731+ skb = dev_alloc_skb(result);
1732+ if (skb) {
1733+ memcpy(skb_put(skb, result), packet, result);
1734+ skb->protocol = eth_type_trans(skb, dev);
1735+ skb->dev = dev;
1736+ skb->ip_summed = CHECKSUM_NONE;
1737+ priv->stats.rx_bytes += skb->len;
1738+ priv->stats.rx_packets++;
1739+ netif_rx(skb);
1740+ } else {
1741+ DEBUGPRINT("%s: Failed to allocate skbuff, "
1742+ "packet dropped\n",
1743+ dev->name);
1744+ priv->stats.rx_dropped++;
1745+ }
1746+ } else if (result < 0) {
1747+ DEBUGPRINT("%s: Receive error code %d, packet "
1748+ "dropped\n",
1749+ dev->name, result);
1750+ priv->stats.rx_errors++;
1751+ }
1752+ } while (result != 0);
1753+
1754+ /* Clear any pending interrupts */
1755+ cvmx_write_csr(CVMX_MIXX_ISR(priv->port),
1756+ cvmx_read_csr(CVMX_MIXX_ISR(priv->port)));
1757+ cvmx_read_csr(CVMX_MIXX_ISR(priv->port));
1758+
1759+ return IRQ_HANDLED;
1760+}
1761+
1762+
1763+#ifdef CONFIG_NET_POLL_CONTROLLER
1764+/**
1765+ * This is called when the kernel needs to manually poll the
1766+ * device. For Octeon, this is simply calling the interrupt
1767+ * handler. We actually poll all the devices, not just the
1768+ * one supplied.
1769+ *
1770+ * @param dev Device to poll. Unused
1771+ */
1772+static void device_poll_controller(struct net_device *dev)
1773+{
1774+ do_interrupt(0, dev);
1775+}
1776+#endif
1777+
1778+
1779+/**
1780+ * Open a device for use. Device should be able to send and
1781+ * receive packets after this is called.
1782+ *
1783+ * @param dev Device to bring up
1784+ * @return Zero on success
1785+ */
1786+static int device_open(struct net_device *dev)
1787+{
1788+ /* Clear the statistics whenever the interface is brought up */
1789+ struct device_private *priv = netdev_priv(dev);
1790+ memset(&priv->stats, 0, sizeof(priv->stats));
1791+ cvmx_mgmt_port_enable(priv->port);
1792+ return 0;
1793+}
1794+
1795+
1796+/**
1797+ * Stop an ethernet device. No more packets should be
1798+ * received from this device.
1799+ *
1800+ * @param dev Device to bring down
1801+ * @return Zero on success
1802+ */
1803+static int device_close(struct net_device *dev)
1804+{
1805+ struct device_private *priv = netdev_priv(dev);
1806+ cvmx_mgmt_port_disable(priv->port);
1807+ return 0;
1808+}
1809+
1810+
1811+/**
1812+ * Get the low level ethernet statistics
1813+ *
1814+ * @param dev Device to get the statistics from
1815+ * @return Pointer to the statistics
1816+ */
1817+static struct net_device_stats *device_get_stats(struct net_device *dev)
1818+{
1819+ struct device_private *priv = netdev_priv(dev);
1820+ return &priv->stats;
1821+}
1822+
1823+/**
1824+ * Set the multicast list. Currently unimplemented.
1825+ *
1826+ * @param dev Device to work on
1827+ */
1828+static void ethernet_mgmt_port_set_multicast_list(struct net_device *dev)
1829+{
1830+ struct device_private *priv = netdev_priv(dev);
1831+ int port = priv->port;
1832+ int num_ports;
1833+ if (OCTEON_IS_MODEL(OCTEON_CN52XX))
1834+ num_ports = 2;
1835+ else
1836+ num_ports = 1;
1837+ if (port < num_ports)
1838+ cvmx_mgmt_port_set_multicast_list(port, dev->flags);
1839+}
1840+
1841+/**
1842+ * Set the hardware MAC address for a management port device
1843+ *
1844+ * @param dev Device to change the MAC address for
1845+ * @param addr Address structure to change it too. MAC address is addr + 2.
1846+ * @return Zero on success
1847+ */
1848+static int ethernet_mgmt_port_set_mac_address(struct net_device *dev,
1849+ void *addr)
1850+{
1851+ struct device_private *priv = netdev_priv(dev);
1852+ union cvmx_agl_gmx_prtx_cfg agl_gmx_cfg;
1853+ int port = priv->port;
1854+ int num_ports;
1855+
1856+ if (OCTEON_IS_MODEL(OCTEON_CN52XX))
1857+ num_ports = 2;
1858+ else
1859+ num_ports = 1;
1860+
1861+ memcpy(dev->dev_addr, addr + 2, 6);
1862+
1863+ if (port < num_ports) {
1864+ int i;
1865+ uint8_t *ptr = addr;
1866+ uint64_t mac = 0;
1867+ for (i = 0; i < 6; i++)
1868+ mac = (mac<<8) | (uint64_t)(ptr[i+2]);
1869+
1870+ agl_gmx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
1871+ cvmx_mgmt_port_set_mac(port, mac);
1872+ ethernet_mgmt_port_set_multicast_list(dev);
1873+ cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_cfg.u64);
1874+ }
1875+ return 0;
1876+}
1877+
1878+/**
1879+ * Per network device initialization
1880+ *
1881+ * @param dev Device to initialize
1882+ * @return Zero on success
1883+ */
1884+static int device_init(struct net_device *dev)
1885+{
1886+ struct device_private *priv = netdev_priv(dev);
1887+ uint64_t mac = cvmx_mgmt_port_get_mac(priv->port);
1888+
1889+ dev->hard_start_xmit = packet_transmit;
1890+ dev->get_stats = device_get_stats;
1891+ dev->open = device_open;
1892+ dev->stop = device_close;
1893+#ifdef CONFIG_NET_POLL_CONTROLLER
1894+ dev->poll_controller = device_poll_controller;
1895+#endif
1896+ dev->dev_addr[0] = (mac >> 40) & 0xff;
1897+ dev->dev_addr[1] = (mac >> 32) & 0xff;
1898+ dev->dev_addr[2] = (mac >> 24) & 0xff;
1899+ dev->dev_addr[3] = (mac >> 16) & 0xff;
1900+ dev->dev_addr[4] = (mac >> 8) & 0xff;
1901+ dev->dev_addr[5] = (mac >> 0) & 0xff;
1902+ return 0;
1903+}
1904+
1905+
1906+/**
1907+ * Module/ driver initialization. Creates the linux network
1908+ * devices.
1909+ *
1910+ * @return Zero on success
1911+ */
1912+static int __init ethernet_mgmt_port_init(void)
1913+{
1914+ struct net_device *dev;
1915+ struct device_private *priv;
1916+ union cvmx_mixx_irhwm mix_irhwm;
1917+ union cvmx_mixx_intena mix_intena;
1918+ int num_ports;
1919+ int port;
1920+
1921+ if (!OCTEON_IS_MODEL(OCTEON_CN56XX) && !OCTEON_IS_MODEL(OCTEON_CN52XX))
1922+ return 0;
1923+
1924+ if (OCTEON_IS_MODEL(OCTEON_CN52XX))
1925+ num_ports = 2;
1926+ else
1927+ num_ports = 1;
1928+
1929+ printk("Octeon management port ethernet driver\n");
1930+
1931+ for (port = 0; port < num_ports; port++) {
1932+ if (cvmx_mgmt_port_initialize(port) != CVMX_MGMT_PORT_SUCCESS) {
1933+ pr_err("ERROR: cvmx_mgmt_port_initialize(%d) "
1934+ "failed\n", port);
1935+ return -1;
1936+ }
1937+
1938+ /* Setup is complete, create the virtual ethernet devices */
1939+ dev = alloc_etherdev(sizeof(struct device_private));
1940+ if (dev == NULL) {
1941+ pr_err("ERROR: Failed to allocate ethernet device\n");
1942+ return -1;
1943+ }
1944+
1945+ dev->init = device_init;
1946+ strcpy(dev->name, "mgmt%d");
1947+
1948+ /* Initialize the device private structure. */
1949+ priv = netdev_priv(dev);
1950+ memset(priv, 0, sizeof(struct device_private));
1951+ priv->port = port;
1952+
1953+ if (register_netdev(dev) < 0) {
1954+ pr_err("ERROR: Failed to register ethernet device\n");
1955+ kfree(dev);
1956+ return -1;
1957+ }
1958+
1959+ /* Clear any pending interrupts */
1960+ cvmx_write_csr(CVMX_MIXX_ISR(priv->port),
1961+ cvmx_read_csr(CVMX_MIXX_ISR(priv->port)));
1962+
1963+ /* Register an IRQ hander for to receive interrupts */
1964+ dev->irq =
1965+ (priv->port == 0) ? OCTEON_IRQ_MII0 : OCTEON_IRQ_MII1;
1966+ if (request_irq(dev->irq, do_interrupt, IRQF_SHARED, dev->name,
1967+ dev))
1968+ pr_err("ethernet-mgmt: Failed to assign "
1969+ "interrupt %d\n", dev->irq);
1970+
1971+ /* Interrupt every single RX packet */
1972+ mix_irhwm.u64 = 0;
1973+ mix_irhwm.s.irhwm = 0;
1974+ cvmx_write_csr(CVMX_MIXX_IRHWM(priv->port), mix_irhwm.u64);
1975+
1976+ /* Enable receive interrupts */
1977+ mix_intena.u64 = 0;
1978+ mix_intena.s.ithena = 1;
1979+ cvmx_write_csr(CVMX_MIXX_INTENA(priv->port), mix_intena.u64);
1980+
1981+ global_dev[priv->port] = dev;
1982+
1983+ dev->set_mac_address = ethernet_mgmt_port_set_mac_address;
1984+ dev->set_multicast_list = ethernet_mgmt_port_set_multicast_list;
1985+ }
1986+ return 0;
1987+}
1988+
1989+
1990+/**
1991+ * Module / driver shutdown
1992+ *
1993+ * @return Zero on success
1994+ */
1995+static void __exit ethernet_mgmt_port_cleanup(void)
1996+{
1997+ int port;
1998+ for (port = 0; port < 2; port++) {
1999+ if (global_dev[port]) {
2000+ struct device_private *priv =
2001+ netdev_priv(global_dev[port]);
2002+ /* Disable interrupt */
2003+ cvmx_write_csr(CVMX_MIXX_IRHWM(priv->port), 0);
2004+ cvmx_write_csr(CVMX_MIXX_INTENA(priv->port), 0);
2005+ cvmx_mgmt_port_shutdown(priv->port);
2006+
2007+ /* Free the interrupt handler */
2008+ free_irq(global_dev[port]->irq, global_dev[port]);
2009+
2010+ /* Free the ethernet devices */
2011+ unregister_netdev(global_dev[port]);
2012+ kfree(global_dev[port]);
2013+ global_dev[port] = NULL;
2014+ }
2015+ }
2016+}
2017+
2018+MODULE_LICENSE("GPL");
2019+MODULE_AUTHOR("Cavium Networks <support@caviumnetworks.com>");
2020+MODULE_DESCRIPTION("Cavium Networks Octeon management port ethernet driver.");
2021+module_init(ethernet_mgmt_port_init);
2022+module_exit(ethernet_mgmt_port_cleanup);
2023

Archive Download this file



interactive