Browse Source

[mii] Add generic MII reset function

iPXE provides no support for manually configuring the link speed.
Provide a generic routine which should be able to reset any MII/GMII
PHY and enable autonegotiation.

Prototyped-by: Thomas Miletich <thomas.miletich@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
9b2aabe534
3 changed files with 172 additions and 0 deletions
  1. 85
    0
      src/drivers/net/mii.c
  2. 1
    0
      src/include/ipxe/errfile.h
  3. 86
    0
      src/include/ipxe/mii.h

+ 85
- 0
src/drivers/net/mii.c View File

@@ -0,0 +1,85 @@
1
+/*
2
+ * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ */
19
+
20
+FILE_LICENCE ( GPL2_OR_LATER );
21
+
22
+#include <string.h>
23
+#include <unistd.h>
24
+#include <errno.h>
25
+#include <ipxe/mii.h>
26
+
27
+/** @file
28
+ *
29
+ * Media Independent Interface
30
+ *
31
+ */
32
+
33
+/**
34
+ * Reset MII interface
35
+ *
36
+ * @v mii		MII interface
37
+ * @ret rc		Return status code
38
+ */
39
+int mii_reset ( struct mii_interface *mii ) {
40
+	unsigned int i;
41
+	int bmcr;
42
+	int rc;
43
+
44
+	/* Power-up, enable autonegotiation and initiate reset */
45
+	if ( ( rc = mii_write ( mii, MII_BMCR,
46
+				( BMCR_RESET | BMCR_ANENABLE ) ) ) != 0 ) {
47
+		DBGC ( mii, "MII %p could not write BMCR: %s\n",
48
+		       mii, strerror ( rc ) );
49
+		return rc;
50
+	}
51
+
52
+	/* Wait for reset to complete */
53
+	for ( i = 0 ; i < MII_RESET_MAX_WAIT_MS ; i++ ) {
54
+
55
+		/* Check if reset has completed */
56
+		bmcr = mii_read ( mii, MII_BMCR );
57
+		if ( bmcr < 0 ) {
58
+			rc = bmcr;
59
+			DBGC ( mii, "MII %p could not read BMCR: %s\n",
60
+			       mii, strerror ( rc ) );
61
+			return rc;
62
+		}
63
+
64
+		/* If reset is not complete, delay 1ms and retry */
65
+		if ( bmcr & BMCR_RESET ) {
66
+			mdelay ( 1 );
67
+			continue;
68
+		}
69
+
70
+		/* Force autonegotation on again, in case it was
71
+		 * cleared by the reset.
72
+		 */
73
+		if ( ( rc = mii_write ( mii, MII_BMCR, BMCR_ANENABLE ) ) != 0 ){
74
+			DBGC ( mii, "MII %p could not write BMCR: %s\n",
75
+			       mii, strerror ( rc ) );
76
+			return rc;
77
+		}
78
+
79
+		DBGC ( mii, "MII %p reset after %dms\n", mii, i );
80
+		return 0;
81
+	}
82
+
83
+	DBGC ( mii, "MII %p timed out waiting for reset\n", mii );
84
+	return -ETIMEDOUT;
85
+}

+ 1
- 0
src/include/ipxe/errfile.h View File

@@ -141,6 +141,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
141 141
 #define ERRFILE_ath9k		     ( ERRFILE_DRIVER | 0x005f0000 )
142 142
 #define ERRFILE_ath		     ( ERRFILE_DRIVER | 0x00600000 )
143 143
 #define ERRFILE_vmxnet3		     ( ERRFILE_DRIVER | 0x00610000 )
144
+#define ERRFILE_mii		     ( ERRFILE_DRIVER | 0x00620000 )
144 145
 
145 146
 #define ERRFILE_scsi		     ( ERRFILE_DRIVER | 0x00700000 )
146 147
 #define ERRFILE_arbel		     ( ERRFILE_DRIVER | 0x00710000 )

+ 86
- 0
src/include/ipxe/mii.h View File

@@ -0,0 +1,86 @@
1
+#ifndef _IPXE_MII_H
2
+#define _IPXE_MII_H
3
+
4
+/** @file
5
+ *
6
+ * Media Independent Interface
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER );
11
+
12
+#include <mii.h>
13
+#include <ipxe/netdevice.h>
14
+
15
+struct mii_interface;
16
+
17
+/** MII interface operations */
18
+struct mii_operations {
19
+	/**
20
+	 * Read from MII register
21
+	 *
22
+	 * @v mii		MII interface
23
+	 * @v reg		Register address
24
+	 * @ret data		Data read, or negative error
25
+	 */
26
+	int ( * read ) ( struct mii_interface *mii, unsigned int reg );
27
+	/**
28
+	 * Write to MII register
29
+	 *
30
+	 * @v mii		MII interface
31
+	 * @v reg		Register address
32
+	 * @v data		Data to write
33
+	 * @ret rc		Return status code
34
+	 */
35
+	int ( * write ) ( struct mii_interface *mii, unsigned int reg,
36
+			  unsigned int data );
37
+};
38
+
39
+/** An MII interface */
40
+struct mii_interface {
41
+	/** Interface operations */
42
+	struct mii_operations *op;
43
+};
44
+
45
+/**
46
+ * Initialise MII interface
47
+ *
48
+ * @v mii		MII interface
49
+ * @v op		MII interface operations
50
+ */
51
+static inline __attribute__ (( always_inline )) void
52
+mii_init ( struct mii_interface *mii, struct mii_operations *op ) {
53
+	mii->op = op;
54
+}
55
+
56
+/**
57
+ * Read from MII register
58
+ *
59
+ * @v mii		MII interface
60
+ * @v reg		Register address
61
+ * @ret data		Data read, or negative error
62
+ */
63
+static inline __attribute__ (( always_inline )) int
64
+mii_read ( struct mii_interface *mii, unsigned int reg ) {
65
+	return mii->op->read ( mii, reg );
66
+}
67
+
68
+/**
69
+ * Write to MII register
70
+ *
71
+ * @v mii		MII interface
72
+ * @v reg		Register address
73
+ * @v data		Data to write
74
+ * @ret rc		Return status code
75
+ */
76
+static inline __attribute__ (( always_inline )) int
77
+mii_write ( struct mii_interface *mii, unsigned int reg, unsigned int data ) {
78
+	return mii->op->write ( mii, reg, data );
79
+}
80
+
81
+/** Maximum time to wait for a reset, in milliseconds */
82
+#define MII_RESET_MAX_WAIT_MS 500
83
+
84
+extern int mii_reset ( struct mii_interface *mii );
85
+
86
+#endif /* _IPXE_MII_H */

Loading…
Cancel
Save