Browse Source

[mii] Add bit-bashing interface

Signed-off-by: Sylvie Barlow <sylvie.c.barlow@gmail.com>
Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Sylvie Barlow 6 years ago
parent
commit
c239f0bff2
2 changed files with 217 additions and 0 deletions
  1. 162
    0
      src/drivers/bitbash/mii_bit.c
  2. 55
    0
      src/include/ipxe/mii_bit.h

+ 162
- 0
src/drivers/bitbash/mii_bit.c View File

@@ -0,0 +1,162 @@
1
+/*
2
+ * Copyright (C) 2018 Sylvie Barlow <sylvie.c.barlow@gmail.com>.
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 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
+ * You can also choose to distribute this program under the terms of
20
+ * the Unmodified Binary Distribution Licence (as given in the file
21
+ * COPYING.UBDL), provided that you have satisfied its requirements.
22
+ */
23
+
24
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
+
26
+#include <stdint.h>
27
+#include <unistd.h>
28
+#include <ipxe/bitbash.h>
29
+#include <ipxe/mii_bit.h>
30
+
31
+/**
32
+ * Transfer bits over MII bit-bashing interface
33
+ *
34
+ * @v basher		Bit basher
35
+ * @v mask		Mask
36
+ * @v write		Data to write
37
+ * @ret read		Data read
38
+ */
39
+static uint32_t mii_bit_xfer ( struct bit_basher *basher,
40
+			       uint32_t mask, uint32_t write ) {
41
+	uint32_t read = 0;
42
+	int bit;
43
+
44
+	for ( ; mask ; mask >>= 1 ) {
45
+
46
+		/* Delay */
47
+		udelay ( 1 );
48
+
49
+		/* Write bit to basher */
50
+		write_bit ( basher, MII_BIT_MDIO, ( write & mask ) );
51
+
52
+		/* Read bit from basher */
53
+		bit = read_bit ( basher, MII_BIT_MDIO );
54
+		read <<= 1;
55
+		read |= ( bit & 1 );
56
+
57
+		/* Set clock high */
58
+		write_bit ( basher, MII_BIT_MDC, 1 );
59
+
60
+		/* Delay */
61
+		udelay ( 1 );
62
+
63
+		/* Set clock low */
64
+		write_bit ( basher, MII_BIT_MDC, 0 );
65
+	}
66
+	return read;
67
+}
68
+
69
+/**
70
+ * Read or write via MII bit-bashing interface
71
+ *
72
+ * @v basher		Bit basher
73
+ * @v phy		PHY address
74
+ * @v reg		Register address
75
+ * @v data		Data to write
76
+ * @v cmd		Command
77
+ * @ret data		Data read
78
+ */
79
+static unsigned int mii_bit_rw ( struct bit_basher *basher,
80
+				 unsigned int phy, unsigned int reg,
81
+				 unsigned int data, unsigned int cmd ) {
82
+
83
+	/* Initiate drive for write */
84
+	write_bit ( basher, MII_BIT_DRIVE, 1 );
85
+
86
+	/* Write start */
87
+	mii_bit_xfer ( basher, MII_BIT_START_MASK, MII_BIT_START );
88
+
89
+	/* Write command */
90
+	mii_bit_xfer ( basher, MII_BIT_CMD_MASK, cmd );
91
+
92
+	/* Write PHY address */
93
+	mii_bit_xfer ( basher, MII_BIT_PHY_MASK, phy );
94
+
95
+	/* Write register address */
96
+	mii_bit_xfer ( basher, MII_BIT_REG_MASK, reg );
97
+
98
+	/* Switch drive to read if applicable */
99
+	write_bit ( basher, MII_BIT_DRIVE, ( cmd & MII_BIT_CMD_RW ) );
100
+
101
+	/* Allow space for turnaround */
102
+	mii_bit_xfer ( basher, MII_BIT_SWITCH_MASK, MII_BIT_SWITCH );
103
+
104
+	/* Read or write data */
105
+	data = mii_bit_xfer (basher, MII_BIT_DATA_MASK, data );
106
+
107
+	/* Initiate drive for read */
108
+	write_bit ( basher, MII_BIT_DRIVE, 0 );
109
+
110
+	return data;
111
+}
112
+
113
+/**
114
+ * Read from MII register
115
+ *
116
+ * @v mdio		MII interface
117
+ * @v phy		PHY address
118
+ * @v reg		Register address
119
+ * @ret data		Data read, or negative error
120
+ */
121
+static int mii_bit_read ( struct mii_interface *mdio, unsigned int phy,
122
+			  unsigned int reg ) {
123
+	struct mii_bit_basher *miibit =
124
+		container_of ( mdio, struct mii_bit_basher, mdio );
125
+	struct bit_basher *basher = &miibit->basher;
126
+
127
+	return mii_bit_rw ( basher, phy, reg, 0, MII_BIT_CMD_READ );
128
+}
129
+
130
+/**
131
+ * Write to MII register
132
+ *
133
+ * @v mdio		MII interface
134
+ * @v phy		PHY address
135
+ * @v reg		Register address
136
+ * @v data		Data to write
137
+ * @ret rc		Return status code
138
+ */
139
+static int mii_bit_write ( struct mii_interface *mdio, unsigned int phy,
140
+			   unsigned int reg, unsigned int data ) {
141
+	struct mii_bit_basher *miibit =
142
+		container_of ( mdio, struct mii_bit_basher, mdio );
143
+	struct bit_basher *basher = &miibit->basher;
144
+
145
+	mii_bit_rw ( basher, phy, reg, data, MII_BIT_CMD_WRITE );
146
+	return 0;
147
+}
148
+
149
+/** MII bit basher operations */
150
+static struct mii_operations mii_bit_op = {
151
+	.read = mii_bit_read,
152
+	.write = mii_bit_write,
153
+};
154
+
155
+/**
156
+ * Initialise bit-bashing interface
157
+ *
158
+ * @v miibit		MII bit basher
159
+ */
160
+void init_mii_bit_basher ( struct mii_bit_basher *miibit ) {
161
+	mdio_init ( &miibit->mdio, &mii_bit_op );
162
+};

+ 55
- 0
src/include/ipxe/mii_bit.h View File

@@ -0,0 +1,55 @@
1
+#ifndef _IPXE_MII_BIT_H
2
+#define _IPXE_MII_BIT_H
3
+
4
+/** @file
5
+ *
6
+ * MII bit-bashing interface
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
+
12
+#include <ipxe/mii.h>
13
+#include <ipxe/bitbash.h>
14
+
15
+#define MII_BIT_START		0xffffffff	/**< Start */
16
+#define MII_BIT_START_MASK	0x80000000	/**< Start mask */
17
+
18
+#define MII_BIT_CMD_MASK	0x00000008	/**< Command mask */
19
+#define MII_BIT_CMD_READ	0x00000006	/**< Command read */
20
+#define MII_BIT_CMD_WRITE	0x00000005	/**< Command write */
21
+#define MII_BIT_CMD_RW		0x00000001	/**< Command read or write */
22
+
23
+#define MII_BIT_PHY_MASK	0x00000010	/**< PHY mask */
24
+
25
+#define MII_BIT_REG_MASK	0x00000010	/**< Register mask */
26
+
27
+#define MII_BIT_SWITCH		0x00000002	/**< Switch */
28
+#define MII_BIT_SWITCH_MASK	0x00000002	/**< Switch mask */
29
+
30
+#define MII_BIT_DATA_MASK	0x00008000	/**< Data mask */
31
+
32
+/** A bit-bashing MII interface */
33
+struct mii_bit_basher {
34
+	/** MII interface */
35
+	struct mii_interface mdio;
36
+	/** Bit-bashing interface */
37
+	struct bit_basher basher;
38
+};
39
+
40
+/** Bit indices used for MII bit-bashing interface */
41
+enum {
42
+	/** MII clock */
43
+	MII_BIT_MDC = 0,
44
+	/** MII data */
45
+	MII_BIT_MDIO,
46
+	/** MII data direction */
47
+	MII_BIT_DRIVE,
48
+};
49
+
50
+/** Delay between MDC transitions */
51
+#define MII_BIT_UDELAY 1
52
+
53
+extern void init_mii_bit_basher ( struct mii_bit_basher *miibit );
54
+
55
+#endif /* _IPXE_MII_BIT_H */

Loading…
Cancel
Save