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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
diff -Naur linux-2.4.31.org/drivers/net/au1000_eth.c linux-2.4.31/drivers/net/au1000_eth.c
--- linux-2.4.31.org/drivers/net/au1000_eth.c 2005-01-19 09:09:56.000000000 -0500
+++ linux-2.4.31/drivers/net/au1000_eth.c 2005-08-22 12:24:31.000000000 -0400
@@ -595,6 +595,97 @@
return 0;
}
+int ns_83847_reset(struct net_device *dev, int phy_addr)
+ {
+ s16 mii_control, timeout;
+
+ // printk("ns_reset\n");
+ mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+ mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
+ mdelay(1);
+ for (timeout = 100; timeout > 0; --timeout) {
+ mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+ if ((mii_control & MII_CNTL_RESET) == 0)
+ break;
+ mdelay(1);
+ }
+ if (mii_control & MII_CNTL_RESET) {
+ printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
+ return -1;
+ }
+ return 0;
+ }
+
+int ns_83847_init(struct net_device *dev, int phy_addr)
+ {
+ s16 data;
+ // printk("ns_init\n");
+
+ /* Stop auto-negotiation */
+ // data = mdio_read(dev, phy_addr, MII_CONTROL);
+ // mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
+ // mdio_write(dev, phy_addr, 0, 0x0000);
+ mdio_write(dev, phy_addr, MII_CONTROL, MII_CNTL_F100 /* | MII_CNTL_FDX */);
+
+ /* Set advertisement to 10/100 and Half/Full duplex (full capabilities) */
+ data = mdio_read(dev, phy_addr, MII_ANADV);
+ /* obs PAUSE bit */
+ data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T; /* MII_NWAY_T4 not sopported */ ;
+ mdio_write(dev, phy_addr, MII_ANADV, data);
+
+ /* Bypass led stretching? */
+ data = mdio_read(dev, phy_addr, MII_NS_PHYCTRL);
+ data |= MII_NS_PHYCTRL_BP_STRETCH;
+ mdio_write(dev, phy_addr, MII_NS_PHYCTRL, data);
+
+ /* Restart auto-negotiation */
+ data = mdio_read(dev, phy_addr, MII_CONTROL);
+ data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
+ mdio_write(dev, phy_addr, MII_CONTROL, data);
+
+ return 0;
+ }
+
+int ns_83847_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
+ {
+ u16 mii_data;
+ struct au1000_private *aup;
+
+ if (!dev) {
+ printk(KERN_ERR "ns_83847_status error: NULL dev\n");
+ return -1;
+ }
+ aup = (struct au1000_private *) dev->priv;
+
+ mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
+ // printk("ns_status: %04x\n", mii_data);
+ if (mii_data & MII_STAT_LINK) {
+ *link = 1;
+ mii_data = mdio_read(dev, aup->phy_addr, MII_NS_PHYSTS);
+ if (mii_data & MII_NS_PHYSTS_SPEED_10) {
+ *speed = IF_PORT_10BASET;
+ dev->if_port = IF_PORT_10BASET;
+ }
+ else {
+ if (mii_data & MII_NS_PHYSTS_DUPLEX_FULL) {
+ *speed = IF_PORT_100BASEFX;
+ dev->if_port = IF_PORT_100BASEFX;
+ }
+ else {
+ *speed = IF_PORT_100BASETX;
+ dev->if_port = IF_PORT_100BASETX;
+ }
+ }
+
+ }
+ else {
+ *link = 0;
+ *speed = 0;
+ dev->if_port = IF_PORT_UNKNOWN;
+ }
+ return 0;
+ }
+
#ifdef CONFIG_MIPS_BOSPORUS
int stub_init(struct net_device *dev, int phy_addr)
{
@@ -620,6 +711,12 @@
}
#endif
+struct phy_ops ns_83847_ops = {
+ ns_83847_init,
+ ns_83847_reset,
+ ns_83847_status,
+};
+
struct phy_ops bcm_5201_ops = {
bcm_5201_init,
bcm_5201_reset,
@@ -679,6 +776,7 @@
{"LSI 80227 10/100 BaseT PHY",0x0016,0xf840, &lsi_80227_ops,0},
{"Intel LXT971A Dual Speed PHY",0x0013,0x78e2, &lxt971a_ops,0},
{"Kendin KS8995M 10/100 BaseT PHY",0x0022,0x1450, &ks8995m_ops,0},
+ {"Natsemi DP83847 PHY", 0x2000, 0x5c30, &ns_83847_ops },
#ifdef CONFIG_MIPS_BOSPORUS
{"Stub", 0x1234, 0x5678, &stub_ops },
#endif
@@ -872,6 +970,8 @@
}
}
}
+ printk(KERN_ERR "%s: Au1x No MII transceivers found!\n", dev->name);
+ return -1;
found:
#ifdef CONFIG_MIPS_BOSPORUS
diff -Naur linux-2.4.31.org/drivers/net/au1000_eth.h linux-2.4.31/drivers/net/au1000_eth.h
--- linux-2.4.31.org/drivers/net/au1000_eth.h 2004-02-18 08:36:31.000000000 -0500
+++ linux-2.4.31/drivers/net/au1000_eth.h 2005-08-22 12:31:37.000000000 -0400
@@ -86,6 +86,27 @@
#define MII_STAT_CAN_TX_FDX 0x4000
#define MII_STAT_CAN_T4 0x8000
+/* mii registers for NS 83847 */
+#define MII_NS_PHYSTS 0x10
+#define MII_NS_FCSCR 0x14
+#define MII_NS_RECR 0x15
+#define MII_NS_PCSR 0x16
+#define MII_NS_PHYCTRL 0x19
+#define MII_NS_10BTSCR 0x1a
+#define MII_NS_CDCTRL 0x1b
+
+/* MII_NS_PHYSTS bits */
+#define MII_NS_PHYSTS_LINK (1)
+#define MII_NS_PHYSTS_SPEED_10 (1<<1)
+#define MII_NS_PHYSTS_DUPLEX_FULL (1<<2)
+
+/* MII_NS_PHYCTRL bits */
+#define MII_NS_PHYCTRL_BP_STRETCH (1<<8)
+
+/* MII_NS_CDCTRL bits */
+#define MII_NS_CDCTRL_CD_ENABLE (1<<15)
+#define MII_NS_CDCTRL_RISETIME (1<<11)
+#define MII_NS_CDCTRL_FALLTIME (1<<9)
#define MII_ID1_OUI_LO 0xFC00 /* low bits of OUI mask */
#define MII_ID1_MODEL 0x03F0 /* model number */
|