1a88394cfSJeff Kirsher /*
23396c782SPaul Gortmaker drivers/net/ethernet/dec/tulip/media.c
3a88394cfSJeff Kirsher
4a88394cfSJeff Kirsher Copyright 2000,2001 The Linux Kernel Team
5a88394cfSJeff Kirsher Written/copyright 1994-2001 by Donald Becker.
6a88394cfSJeff Kirsher
7a88394cfSJeff Kirsher This software may be used and distributed according to the terms
8a88394cfSJeff Kirsher of the GNU General Public License, incorporated herein by reference.
9a88394cfSJeff Kirsher
10a88394cfSJeff Kirsher Please submit bugs to http://bugzilla.kernel.org/ .
11a88394cfSJeff Kirsher */
12a88394cfSJeff Kirsher
13a88394cfSJeff Kirsher #include <linux/kernel.h>
14a88394cfSJeff Kirsher #include <linux/mii.h>
15a88394cfSJeff Kirsher #include <linux/delay.h>
16a88394cfSJeff Kirsher #include <linux/pci.h>
17a88394cfSJeff Kirsher #include "tulip.h"
18a88394cfSJeff Kirsher
19a88394cfSJeff Kirsher
20a88394cfSJeff Kirsher /* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
21a88394cfSJeff Kirsher met by back-to-back PCI I/O cycles, but we insert a delay to avoid
22a88394cfSJeff Kirsher "overclocking" issues or future 66Mhz PCI. */
23a88394cfSJeff Kirsher #define mdio_delay() ioread32(mdio_addr)
24a88394cfSJeff Kirsher
25a88394cfSJeff Kirsher /* Read and write the MII registers using software-generated serial
26a88394cfSJeff Kirsher MDIO protocol. It is just different enough from the EEPROM protocol
27a88394cfSJeff Kirsher to not share code. The maxium data clock rate is 2.5 Mhz. */
28a88394cfSJeff Kirsher #define MDIO_SHIFT_CLK 0x10000
29a88394cfSJeff Kirsher #define MDIO_DATA_WRITE0 0x00000
30a88394cfSJeff Kirsher #define MDIO_DATA_WRITE1 0x20000
31a88394cfSJeff Kirsher #define MDIO_ENB 0x00000 /* Ignore the 0x02000 databook setting. */
32a88394cfSJeff Kirsher #define MDIO_ENB_IN 0x40000
33a88394cfSJeff Kirsher #define MDIO_DATA_READ 0x80000
34a88394cfSJeff Kirsher
35a88394cfSJeff Kirsher static const unsigned char comet_miireg2offset[32] = {
36a88394cfSJeff Kirsher 0xB4, 0xB8, 0xBC, 0xC0, 0xC4, 0xC8, 0xCC, 0, 0,0,0,0, 0,0,0,0,
37a88394cfSJeff Kirsher 0,0xD0,0,0, 0,0,0,0, 0,0,0,0, 0, 0xD4, 0xD8, 0xDC, };
38a88394cfSJeff Kirsher
39a88394cfSJeff Kirsher
40a88394cfSJeff Kirsher /* MII transceiver control section.
41a88394cfSJeff Kirsher Read and write the MII registers using software-generated serial
42a88394cfSJeff Kirsher MDIO protocol.
43a88394cfSJeff Kirsher See IEEE 802.3-2002.pdf (Section 2, Chapter "22.2.4 Management functions")
44a88394cfSJeff Kirsher or DP83840A data sheet for more details.
45a88394cfSJeff Kirsher */
46a88394cfSJeff Kirsher
tulip_mdio_read(struct net_device * dev,int phy_id,int location)47a88394cfSJeff Kirsher int tulip_mdio_read(struct net_device *dev, int phy_id, int location)
48a88394cfSJeff Kirsher {
49a88394cfSJeff Kirsher struct tulip_private *tp = netdev_priv(dev);
50a88394cfSJeff Kirsher int i;
51a88394cfSJeff Kirsher int read_cmd = (0xf6 << 10) | ((phy_id & 0x1f) << 5) | location;
52a88394cfSJeff Kirsher int retval = 0;
53a88394cfSJeff Kirsher void __iomem *ioaddr = tp->base_addr;
54a88394cfSJeff Kirsher void __iomem *mdio_addr = ioaddr + CSR9;
55a88394cfSJeff Kirsher unsigned long flags;
56a88394cfSJeff Kirsher
57a88394cfSJeff Kirsher if (location & ~0x1f)
58a88394cfSJeff Kirsher return 0xffff;
59a88394cfSJeff Kirsher
60a88394cfSJeff Kirsher if (tp->chip_id == COMET && phy_id == 30) {
61a88394cfSJeff Kirsher if (comet_miireg2offset[location])
62a88394cfSJeff Kirsher return ioread32(ioaddr + comet_miireg2offset[location]);
63a88394cfSJeff Kirsher return 0xffff;
64a88394cfSJeff Kirsher }
65a88394cfSJeff Kirsher
66a88394cfSJeff Kirsher spin_lock_irqsave(&tp->mii_lock, flags);
67a88394cfSJeff Kirsher if (tp->chip_id == LC82C168) {
68a88394cfSJeff Kirsher iowrite32(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0);
69a88394cfSJeff Kirsher ioread32(ioaddr + 0xA0);
70a88394cfSJeff Kirsher ioread32(ioaddr + 0xA0);
71a88394cfSJeff Kirsher for (i = 1000; i >= 0; --i) {
72a88394cfSJeff Kirsher barrier();
73a88394cfSJeff Kirsher if ( ! ((retval = ioread32(ioaddr + 0xA0)) & 0x80000000))
74a88394cfSJeff Kirsher break;
75a88394cfSJeff Kirsher }
76a88394cfSJeff Kirsher spin_unlock_irqrestore(&tp->mii_lock, flags);
77a88394cfSJeff Kirsher return retval & 0xffff;
78a88394cfSJeff Kirsher }
79a88394cfSJeff Kirsher
80a88394cfSJeff Kirsher /* Establish sync by sending at least 32 logic ones. */
81a88394cfSJeff Kirsher for (i = 32; i >= 0; i--) {
82a88394cfSJeff Kirsher iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
83a88394cfSJeff Kirsher mdio_delay();
84a88394cfSJeff Kirsher iowrite32(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
85a88394cfSJeff Kirsher mdio_delay();
86a88394cfSJeff Kirsher }
87a88394cfSJeff Kirsher /* Shift the read command bits out. */
88a88394cfSJeff Kirsher for (i = 15; i >= 0; i--) {
89a88394cfSJeff Kirsher int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
90a88394cfSJeff Kirsher
91a88394cfSJeff Kirsher iowrite32(MDIO_ENB | dataval, mdio_addr);
92a88394cfSJeff Kirsher mdio_delay();
93a88394cfSJeff Kirsher iowrite32(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
94a88394cfSJeff Kirsher mdio_delay();
95a88394cfSJeff Kirsher }
96a88394cfSJeff Kirsher /* Read the two transition, 16 data, and wire-idle bits. */
97a88394cfSJeff Kirsher for (i = 19; i > 0; i--) {
98a88394cfSJeff Kirsher iowrite32(MDIO_ENB_IN, mdio_addr);
99a88394cfSJeff Kirsher mdio_delay();
100a88394cfSJeff Kirsher retval = (retval << 1) | ((ioread32(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
101a88394cfSJeff Kirsher iowrite32(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
102a88394cfSJeff Kirsher mdio_delay();
103a88394cfSJeff Kirsher }
104a88394cfSJeff Kirsher
105a88394cfSJeff Kirsher spin_unlock_irqrestore(&tp->mii_lock, flags);
106a88394cfSJeff Kirsher return (retval>>1) & 0xffff;
107a88394cfSJeff Kirsher }
108a88394cfSJeff Kirsher
tulip_mdio_write(struct net_device * dev,int phy_id,int location,int val)109a88394cfSJeff Kirsher void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val)
110a88394cfSJeff Kirsher {
111a88394cfSJeff Kirsher struct tulip_private *tp = netdev_priv(dev);
112a88394cfSJeff Kirsher int i;
113a88394cfSJeff Kirsher int cmd = (0x5002 << 16) | ((phy_id & 0x1f) << 23) | (location<<18) | (val & 0xffff);
114a88394cfSJeff Kirsher void __iomem *ioaddr = tp->base_addr;
115a88394cfSJeff Kirsher void __iomem *mdio_addr = ioaddr + CSR9;
116a88394cfSJeff Kirsher unsigned long flags;
117a88394cfSJeff Kirsher
118a88394cfSJeff Kirsher if (location & ~0x1f)
119a88394cfSJeff Kirsher return;
120a88394cfSJeff Kirsher
121a88394cfSJeff Kirsher if (tp->chip_id == COMET && phy_id == 30) {
122a88394cfSJeff Kirsher if (comet_miireg2offset[location])
123a88394cfSJeff Kirsher iowrite32(val, ioaddr + comet_miireg2offset[location]);
124a88394cfSJeff Kirsher return;
125a88394cfSJeff Kirsher }
126a88394cfSJeff Kirsher
127a88394cfSJeff Kirsher spin_lock_irqsave(&tp->mii_lock, flags);
128a88394cfSJeff Kirsher if (tp->chip_id == LC82C168) {
129a88394cfSJeff Kirsher iowrite32(cmd, ioaddr + 0xA0);
130a88394cfSJeff Kirsher for (i = 1000; i >= 0; --i) {
131a88394cfSJeff Kirsher barrier();
132a88394cfSJeff Kirsher if ( ! (ioread32(ioaddr + 0xA0) & 0x80000000))
133a88394cfSJeff Kirsher break;
134a88394cfSJeff Kirsher }
135a88394cfSJeff Kirsher spin_unlock_irqrestore(&tp->mii_lock, flags);
136a88394cfSJeff Kirsher return;
137a88394cfSJeff Kirsher }
138a88394cfSJeff Kirsher
139a88394cfSJeff Kirsher /* Establish sync by sending 32 logic ones. */
140a88394cfSJeff Kirsher for (i = 32; i >= 0; i--) {
141a88394cfSJeff Kirsher iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
142a88394cfSJeff Kirsher mdio_delay();
143a88394cfSJeff Kirsher iowrite32(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
144a88394cfSJeff Kirsher mdio_delay();
145a88394cfSJeff Kirsher }
146a88394cfSJeff Kirsher /* Shift the command bits out. */
147a88394cfSJeff Kirsher for (i = 31; i >= 0; i--) {
148a88394cfSJeff Kirsher int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
149a88394cfSJeff Kirsher iowrite32(MDIO_ENB | dataval, mdio_addr);
150a88394cfSJeff Kirsher mdio_delay();
151a88394cfSJeff Kirsher iowrite32(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
152a88394cfSJeff Kirsher mdio_delay();
153a88394cfSJeff Kirsher }
154a88394cfSJeff Kirsher /* Clear out extra bits. */
155a88394cfSJeff Kirsher for (i = 2; i > 0; i--) {
156a88394cfSJeff Kirsher iowrite32(MDIO_ENB_IN, mdio_addr);
157a88394cfSJeff Kirsher mdio_delay();
158a88394cfSJeff Kirsher iowrite32(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
159a88394cfSJeff Kirsher mdio_delay();
160a88394cfSJeff Kirsher }
161a88394cfSJeff Kirsher
162a88394cfSJeff Kirsher spin_unlock_irqrestore(&tp->mii_lock, flags);
163a88394cfSJeff Kirsher }
164a88394cfSJeff Kirsher
165a88394cfSJeff Kirsher
166a88394cfSJeff Kirsher /* Set up the transceiver control registers for the selected media type. */
tulip_select_media(struct net_device * dev,int startup)167a88394cfSJeff Kirsher void tulip_select_media(struct net_device *dev, int startup)
168a88394cfSJeff Kirsher {
169a88394cfSJeff Kirsher struct tulip_private *tp = netdev_priv(dev);
170a88394cfSJeff Kirsher void __iomem *ioaddr = tp->base_addr;
171a88394cfSJeff Kirsher struct mediatable *mtable = tp->mtable;
172a88394cfSJeff Kirsher u32 new_csr6;
173a88394cfSJeff Kirsher int i;
174a88394cfSJeff Kirsher
175a88394cfSJeff Kirsher if (mtable) {
176a88394cfSJeff Kirsher struct medialeaf *mleaf = &mtable->mleaf[tp->cur_index];
177a88394cfSJeff Kirsher unsigned char *p = mleaf->leafdata;
178a88394cfSJeff Kirsher switch (mleaf->type) {
179a88394cfSJeff Kirsher case 0: /* 21140 non-MII xcvr. */
180a88394cfSJeff Kirsher if (tulip_debug > 1)
181a88394cfSJeff Kirsher netdev_dbg(dev, "Using a 21140 non-MII transceiver with control setting %02x\n",
182a88394cfSJeff Kirsher p[1]);
183a88394cfSJeff Kirsher dev->if_port = p[0];
184a88394cfSJeff Kirsher if (startup)
185a88394cfSJeff Kirsher iowrite32(mtable->csr12dir | 0x100, ioaddr + CSR12);
186a88394cfSJeff Kirsher iowrite32(p[1], ioaddr + CSR12);
187a88394cfSJeff Kirsher new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18);
188a88394cfSJeff Kirsher break;
189a88394cfSJeff Kirsher case 2: case 4: {
190a88394cfSJeff Kirsher u16 setup[5];
191a88394cfSJeff Kirsher u32 csr13val, csr14val, csr15dir, csr15val;
192a88394cfSJeff Kirsher for (i = 0; i < 5; i++)
193a88394cfSJeff Kirsher setup[i] = get_u16(&p[i*2 + 1]);
194a88394cfSJeff Kirsher
195a88394cfSJeff Kirsher dev->if_port = p[0] & MEDIA_MASK;
196a88394cfSJeff Kirsher if (tulip_media_cap[dev->if_port] & MediaAlwaysFD)
197a88394cfSJeff Kirsher tp->full_duplex = 1;
198a88394cfSJeff Kirsher
199a88394cfSJeff Kirsher if (startup && mtable->has_reset) {
200a88394cfSJeff Kirsher struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset];
201a88394cfSJeff Kirsher unsigned char *rst = rleaf->leafdata;
202a88394cfSJeff Kirsher if (tulip_debug > 1)
203a88394cfSJeff Kirsher netdev_dbg(dev, "Resetting the transceiver\n");
204a88394cfSJeff Kirsher for (i = 0; i < rst[0]; i++)
205a88394cfSJeff Kirsher iowrite32(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15);
206a88394cfSJeff Kirsher }
207a88394cfSJeff Kirsher if (tulip_debug > 1)
208a88394cfSJeff Kirsher netdev_dbg(dev, "21143 non-MII %s transceiver control %04x/%04x\n",
209a88394cfSJeff Kirsher medianame[dev->if_port],
210a88394cfSJeff Kirsher setup[0], setup[1]);
211a88394cfSJeff Kirsher if (p[0] & 0x40) { /* SIA (CSR13-15) setup values are provided. */
212a88394cfSJeff Kirsher csr13val = setup[0];
213a88394cfSJeff Kirsher csr14val = setup[1];
214a88394cfSJeff Kirsher csr15dir = (setup[3]<<16) | setup[2];
215a88394cfSJeff Kirsher csr15val = (setup[4]<<16) | setup[2];
216a88394cfSJeff Kirsher iowrite32(0, ioaddr + CSR13);
217a88394cfSJeff Kirsher iowrite32(csr14val, ioaddr + CSR14);
218a88394cfSJeff Kirsher iowrite32(csr15dir, ioaddr + CSR15); /* Direction */
219a88394cfSJeff Kirsher iowrite32(csr15val, ioaddr + CSR15); /* Data */
220a88394cfSJeff Kirsher iowrite32(csr13val, ioaddr + CSR13);
221a88394cfSJeff Kirsher } else {
222a88394cfSJeff Kirsher csr13val = 1;
223a88394cfSJeff Kirsher csr14val = 0;
224a88394cfSJeff Kirsher csr15dir = (setup[0]<<16) | 0x0008;
225a88394cfSJeff Kirsher csr15val = (setup[1]<<16) | 0x0008;
226a88394cfSJeff Kirsher if (dev->if_port <= 4)
227a88394cfSJeff Kirsher csr14val = t21142_csr14[dev->if_port];
228a88394cfSJeff Kirsher if (startup) {
229a88394cfSJeff Kirsher iowrite32(0, ioaddr + CSR13);
230a88394cfSJeff Kirsher iowrite32(csr14val, ioaddr + CSR14);
231a88394cfSJeff Kirsher }
232a88394cfSJeff Kirsher iowrite32(csr15dir, ioaddr + CSR15); /* Direction */
233a88394cfSJeff Kirsher iowrite32(csr15val, ioaddr + CSR15); /* Data */
234a88394cfSJeff Kirsher if (startup) iowrite32(csr13val, ioaddr + CSR13);
235a88394cfSJeff Kirsher }
236a88394cfSJeff Kirsher if (tulip_debug > 1)
237a88394cfSJeff Kirsher netdev_dbg(dev, "Setting CSR15 to %08x/%08x\n",
238a88394cfSJeff Kirsher csr15dir, csr15val);
239a88394cfSJeff Kirsher if (mleaf->type == 4)
240a88394cfSJeff Kirsher new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18);
241a88394cfSJeff Kirsher else
242a88394cfSJeff Kirsher new_csr6 = 0x82420000;
243a88394cfSJeff Kirsher break;
244a88394cfSJeff Kirsher }
245a88394cfSJeff Kirsher case 1: case 3: {
246a88394cfSJeff Kirsher int phy_num = p[0];
247a88394cfSJeff Kirsher int init_length = p[1];
248a88394cfSJeff Kirsher u16 *misc_info, tmp_info;
249a88394cfSJeff Kirsher
250a88394cfSJeff Kirsher dev->if_port = 11;
251a88394cfSJeff Kirsher new_csr6 = 0x020E0000;
252a88394cfSJeff Kirsher if (mleaf->type == 3) { /* 21142 */
253a88394cfSJeff Kirsher u16 *init_sequence = (u16*)(p+2);
254a88394cfSJeff Kirsher u16 *reset_sequence = &((u16*)(p+3))[init_length];
255a88394cfSJeff Kirsher int reset_length = p[2 + init_length*2];
256a88394cfSJeff Kirsher misc_info = reset_sequence + reset_length;
257a88394cfSJeff Kirsher if (startup) {
258a88394cfSJeff Kirsher int timeout = 10; /* max 1 ms */
259a88394cfSJeff Kirsher for (i = 0; i < reset_length; i++)
260a88394cfSJeff Kirsher iowrite32(get_u16(&reset_sequence[i]) << 16, ioaddr + CSR15);
261a88394cfSJeff Kirsher
262a88394cfSJeff Kirsher /* flush posted writes */
263a88394cfSJeff Kirsher ioread32(ioaddr + CSR15);
264a88394cfSJeff Kirsher
265a88394cfSJeff Kirsher /* Sect 3.10.3 in DP83840A.pdf (p39) */
266a88394cfSJeff Kirsher udelay(500);
267a88394cfSJeff Kirsher
268a88394cfSJeff Kirsher /* Section 4.2 in DP83840A.pdf (p43) */
269a88394cfSJeff Kirsher /* and IEEE 802.3 "22.2.4.1.1 Reset" */
270a88394cfSJeff Kirsher while (timeout-- &&
271a88394cfSJeff Kirsher (tulip_mdio_read (dev, phy_num, MII_BMCR) & BMCR_RESET))
272a88394cfSJeff Kirsher udelay(100);
273a88394cfSJeff Kirsher }
274a88394cfSJeff Kirsher for (i = 0; i < init_length; i++)
275a88394cfSJeff Kirsher iowrite32(get_u16(&init_sequence[i]) << 16, ioaddr + CSR15);
276a88394cfSJeff Kirsher
277a88394cfSJeff Kirsher ioread32(ioaddr + CSR15); /* flush posted writes */
278a88394cfSJeff Kirsher } else {
279a88394cfSJeff Kirsher u8 *init_sequence = p + 2;
280a88394cfSJeff Kirsher u8 *reset_sequence = p + 3 + init_length;
281a88394cfSJeff Kirsher int reset_length = p[2 + init_length];
282a88394cfSJeff Kirsher misc_info = (u16*)(reset_sequence + reset_length);
283a88394cfSJeff Kirsher if (startup) {
284a88394cfSJeff Kirsher int timeout = 10; /* max 1 ms */
285a88394cfSJeff Kirsher iowrite32(mtable->csr12dir | 0x100, ioaddr + CSR12);
286a88394cfSJeff Kirsher for (i = 0; i < reset_length; i++)
287a88394cfSJeff Kirsher iowrite32(reset_sequence[i], ioaddr + CSR12);
288a88394cfSJeff Kirsher
289a88394cfSJeff Kirsher /* flush posted writes */
290a88394cfSJeff Kirsher ioread32(ioaddr + CSR12);
291a88394cfSJeff Kirsher
292a88394cfSJeff Kirsher /* Sect 3.10.3 in DP83840A.pdf (p39) */
293a88394cfSJeff Kirsher udelay(500);
294a88394cfSJeff Kirsher
295a88394cfSJeff Kirsher /* Section 4.2 in DP83840A.pdf (p43) */
296a88394cfSJeff Kirsher /* and IEEE 802.3 "22.2.4.1.1 Reset" */
297a88394cfSJeff Kirsher while (timeout-- &&
298a88394cfSJeff Kirsher (tulip_mdio_read (dev, phy_num, MII_BMCR) & BMCR_RESET))
299a88394cfSJeff Kirsher udelay(100);
300a88394cfSJeff Kirsher }
301a88394cfSJeff Kirsher for (i = 0; i < init_length; i++)
302a88394cfSJeff Kirsher iowrite32(init_sequence[i], ioaddr + CSR12);
303a88394cfSJeff Kirsher
304a88394cfSJeff Kirsher ioread32(ioaddr + CSR12); /* flush posted writes */
305a88394cfSJeff Kirsher }
306a88394cfSJeff Kirsher
307a88394cfSJeff Kirsher tmp_info = get_u16(&misc_info[1]);
308a88394cfSJeff Kirsher if (tmp_info)
309a88394cfSJeff Kirsher tp->advertising[phy_num] = tmp_info | 1;
310a88394cfSJeff Kirsher if (tmp_info && startup < 2) {
311a88394cfSJeff Kirsher if (tp->mii_advertise == 0)
312a88394cfSJeff Kirsher tp->mii_advertise = tp->advertising[phy_num];
313a88394cfSJeff Kirsher if (tulip_debug > 1)
314a88394cfSJeff Kirsher netdev_dbg(dev, " Advertising %04x on MII %d\n",
315a88394cfSJeff Kirsher tp->mii_advertise,
316a88394cfSJeff Kirsher tp->phys[phy_num]);
317a88394cfSJeff Kirsher tulip_mdio_write(dev, tp->phys[phy_num], 4, tp->mii_advertise);
318a88394cfSJeff Kirsher }
319a88394cfSJeff Kirsher break;
320a88394cfSJeff Kirsher }
321a88394cfSJeff Kirsher case 5: case 6: {
322a88394cfSJeff Kirsher new_csr6 = 0; /* FIXME */
323a88394cfSJeff Kirsher
324a88394cfSJeff Kirsher if (startup && mtable->has_reset) {
325a88394cfSJeff Kirsher struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset];
326a88394cfSJeff Kirsher unsigned char *rst = rleaf->leafdata;
327a88394cfSJeff Kirsher if (tulip_debug > 1)
328a88394cfSJeff Kirsher netdev_dbg(dev, "Resetting the transceiver\n");
329a88394cfSJeff Kirsher for (i = 0; i < rst[0]; i++)
330a88394cfSJeff Kirsher iowrite32(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15);
331a88394cfSJeff Kirsher }
332a88394cfSJeff Kirsher
333a88394cfSJeff Kirsher break;
334a88394cfSJeff Kirsher }
335a88394cfSJeff Kirsher default:
336a88394cfSJeff Kirsher netdev_dbg(dev, " Invalid media table selection %d\n",
337a88394cfSJeff Kirsher mleaf->type);
338a88394cfSJeff Kirsher new_csr6 = 0x020E0000;
339a88394cfSJeff Kirsher }
340a88394cfSJeff Kirsher if (tulip_debug > 1)
341a88394cfSJeff Kirsher netdev_dbg(dev, "Using media type %s, CSR12 is %02x\n",
342a88394cfSJeff Kirsher medianame[dev->if_port],
343a88394cfSJeff Kirsher ioread32(ioaddr + CSR12) & 0xff);
344a88394cfSJeff Kirsher } else if (tp->chip_id == LC82C168) {
345a88394cfSJeff Kirsher if (startup && ! tp->medialock)
346a88394cfSJeff Kirsher dev->if_port = tp->mii_cnt ? 11 : 0;
347a88394cfSJeff Kirsher if (tulip_debug > 1)
348a88394cfSJeff Kirsher netdev_dbg(dev, "PNIC PHY status is %3.3x, media %s\n",
349a88394cfSJeff Kirsher ioread32(ioaddr + 0xB8),
350a88394cfSJeff Kirsher medianame[dev->if_port]);
351a88394cfSJeff Kirsher if (tp->mii_cnt) {
352a88394cfSJeff Kirsher new_csr6 = 0x810C0000;
353a88394cfSJeff Kirsher iowrite32(0x0001, ioaddr + CSR15);
354a88394cfSJeff Kirsher iowrite32(0x0201B07A, ioaddr + 0xB8);
355a88394cfSJeff Kirsher } else if (startup) {
356a88394cfSJeff Kirsher /* Start with 10mbps to do autonegotiation. */
357a88394cfSJeff Kirsher iowrite32(0x32, ioaddr + CSR12);
358a88394cfSJeff Kirsher new_csr6 = 0x00420000;
359a88394cfSJeff Kirsher iowrite32(0x0001B078, ioaddr + 0xB8);
360a88394cfSJeff Kirsher iowrite32(0x0201B078, ioaddr + 0xB8);
361a88394cfSJeff Kirsher } else if (dev->if_port == 3 || dev->if_port == 5) {
362a88394cfSJeff Kirsher iowrite32(0x33, ioaddr + CSR12);
363a88394cfSJeff Kirsher new_csr6 = 0x01860000;
364a88394cfSJeff Kirsher /* Trigger autonegotiation. */
365*17bd3a1eSColin Ian King iowrite32(0x0001F868, ioaddr + 0xB8);
366a88394cfSJeff Kirsher } else {
367a88394cfSJeff Kirsher iowrite32(0x32, ioaddr + CSR12);
368a88394cfSJeff Kirsher new_csr6 = 0x00420000;
369a88394cfSJeff Kirsher iowrite32(0x1F078, ioaddr + 0xB8);
370a88394cfSJeff Kirsher }
371a88394cfSJeff Kirsher } else { /* Unknown chip type with no media table. */
372a88394cfSJeff Kirsher if (tp->default_port == 0)
373a88394cfSJeff Kirsher dev->if_port = tp->mii_cnt ? 11 : 3;
374a88394cfSJeff Kirsher if (tulip_media_cap[dev->if_port] & MediaIsMII) {
375a88394cfSJeff Kirsher new_csr6 = 0x020E0000;
376a88394cfSJeff Kirsher } else if (tulip_media_cap[dev->if_port] & MediaIsFx) {
377a88394cfSJeff Kirsher new_csr6 = 0x02860000;
378a88394cfSJeff Kirsher } else
379a88394cfSJeff Kirsher new_csr6 = 0x03860000;
380a88394cfSJeff Kirsher if (tulip_debug > 1)
381a88394cfSJeff Kirsher netdev_dbg(dev, "No media description table, assuming %s transceiver, CSR12 %02x\n",
382a88394cfSJeff Kirsher medianame[dev->if_port],
383a88394cfSJeff Kirsher ioread32(ioaddr + CSR12));
384a88394cfSJeff Kirsher }
385a88394cfSJeff Kirsher
386a88394cfSJeff Kirsher tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0);
387a88394cfSJeff Kirsher
388a88394cfSJeff Kirsher mdelay(1);
389a88394cfSJeff Kirsher }
390a88394cfSJeff Kirsher
391a88394cfSJeff Kirsher /*
392a88394cfSJeff Kirsher Check the MII negotiated duplex and change the CSR6 setting if
393a88394cfSJeff Kirsher required.
394a88394cfSJeff Kirsher Return 0 if everything is OK.
395a88394cfSJeff Kirsher Return < 0 if the transceiver is missing or has no link beat.
396a88394cfSJeff Kirsher */
tulip_check_duplex(struct net_device * dev)397a88394cfSJeff Kirsher int tulip_check_duplex(struct net_device *dev)
398a88394cfSJeff Kirsher {
399a88394cfSJeff Kirsher struct tulip_private *tp = netdev_priv(dev);
400a88394cfSJeff Kirsher unsigned int bmsr, lpa, negotiated, new_csr6;
401a88394cfSJeff Kirsher
402a88394cfSJeff Kirsher bmsr = tulip_mdio_read(dev, tp->phys[0], MII_BMSR);
403a88394cfSJeff Kirsher lpa = tulip_mdio_read(dev, tp->phys[0], MII_LPA);
404a88394cfSJeff Kirsher if (tulip_debug > 1)
405a88394cfSJeff Kirsher dev_info(&dev->dev, "MII status %04x, Link partner report %04x\n",
406a88394cfSJeff Kirsher bmsr, lpa);
407a88394cfSJeff Kirsher if (bmsr == 0xffff)
408a88394cfSJeff Kirsher return -2;
409a88394cfSJeff Kirsher if ((bmsr & BMSR_LSTATUS) == 0) {
410a88394cfSJeff Kirsher int new_bmsr = tulip_mdio_read(dev, tp->phys[0], MII_BMSR);
411a88394cfSJeff Kirsher if ((new_bmsr & BMSR_LSTATUS) == 0) {
412a88394cfSJeff Kirsher if (tulip_debug > 1)
413a88394cfSJeff Kirsher dev_info(&dev->dev,
414a88394cfSJeff Kirsher "No link beat on the MII interface, status %04x\n",
415a88394cfSJeff Kirsher new_bmsr);
416a88394cfSJeff Kirsher return -1;
417a88394cfSJeff Kirsher }
418a88394cfSJeff Kirsher }
419a88394cfSJeff Kirsher negotiated = lpa & tp->advertising[0];
420a88394cfSJeff Kirsher tp->full_duplex = mii_duplex(tp->full_duplex_lock, negotiated);
421a88394cfSJeff Kirsher
422a88394cfSJeff Kirsher new_csr6 = tp->csr6;
423a88394cfSJeff Kirsher
424a88394cfSJeff Kirsher if (negotiated & LPA_100) new_csr6 &= ~TxThreshold;
425a88394cfSJeff Kirsher else new_csr6 |= TxThreshold;
426a88394cfSJeff Kirsher if (tp->full_duplex) new_csr6 |= FullDuplex;
427a88394cfSJeff Kirsher else new_csr6 &= ~FullDuplex;
428a88394cfSJeff Kirsher
429a88394cfSJeff Kirsher if (new_csr6 != tp->csr6) {
430a88394cfSJeff Kirsher tp->csr6 = new_csr6;
431a88394cfSJeff Kirsher tulip_restart_rxtx(tp);
432a88394cfSJeff Kirsher
433a88394cfSJeff Kirsher if (tulip_debug > 0)
434a88394cfSJeff Kirsher dev_info(&dev->dev,
435a88394cfSJeff Kirsher "Setting %s-duplex based on MII#%d link partner capability of %04x\n",
436a88394cfSJeff Kirsher tp->full_duplex ? "full" : "half",
437a88394cfSJeff Kirsher tp->phys[0], lpa);
438a88394cfSJeff Kirsher return 1;
439a88394cfSJeff Kirsher }
440a88394cfSJeff Kirsher
441a88394cfSJeff Kirsher return 0;
442a88394cfSJeff Kirsher }
443a88394cfSJeff Kirsher
tulip_find_mii(struct net_device * dev,int board_idx)444779c1a85SBill Pemberton void tulip_find_mii(struct net_device *dev, int board_idx)
445a88394cfSJeff Kirsher {
446a88394cfSJeff Kirsher struct tulip_private *tp = netdev_priv(dev);
447a88394cfSJeff Kirsher int phyn, phy_idx = 0;
448a88394cfSJeff Kirsher int mii_reg0;
449a88394cfSJeff Kirsher int mii_advert;
450a88394cfSJeff Kirsher unsigned int to_advert, new_bmcr, ane_switch;
451a88394cfSJeff Kirsher
452a88394cfSJeff Kirsher /* Find the connected MII xcvrs.
453a88394cfSJeff Kirsher Doing this in open() would allow detecting external xcvrs later,
454a88394cfSJeff Kirsher but takes much time. */
45528f39ef6SDan Carpenter for (phyn = 1; phyn <= 32 && phy_idx < ARRAY_SIZE(tp->phys); phyn++) {
456a88394cfSJeff Kirsher int phy = phyn & 0x1f;
457a88394cfSJeff Kirsher int mii_status = tulip_mdio_read (dev, phy, MII_BMSR);
458a88394cfSJeff Kirsher if ((mii_status & 0x8301) == 0x8001 ||
459a88394cfSJeff Kirsher ((mii_status & BMSR_100BASE4) == 0 &&
460a88394cfSJeff Kirsher (mii_status & 0x7800) != 0)) {
461a88394cfSJeff Kirsher /* preserve Becker logic, gain indentation level */
462a88394cfSJeff Kirsher } else {
463a88394cfSJeff Kirsher continue;
464a88394cfSJeff Kirsher }
465a88394cfSJeff Kirsher
466a88394cfSJeff Kirsher mii_reg0 = tulip_mdio_read (dev, phy, MII_BMCR);
467a88394cfSJeff Kirsher mii_advert = tulip_mdio_read (dev, phy, MII_ADVERTISE);
468a88394cfSJeff Kirsher ane_switch = 0;
469a88394cfSJeff Kirsher
470a88394cfSJeff Kirsher /* if not advertising at all, gen an
471a88394cfSJeff Kirsher * advertising value from the capability
472a88394cfSJeff Kirsher * bits in BMSR
473a88394cfSJeff Kirsher */
474a88394cfSJeff Kirsher if ((mii_advert & ADVERTISE_ALL) == 0) {
475a88394cfSJeff Kirsher unsigned int tmpadv = tulip_mdio_read (dev, phy, MII_BMSR);
476a88394cfSJeff Kirsher mii_advert = ((tmpadv >> 6) & 0x3e0) | 1;
477a88394cfSJeff Kirsher }
478a88394cfSJeff Kirsher
479a88394cfSJeff Kirsher if (tp->mii_advertise) {
480a88394cfSJeff Kirsher tp->advertising[phy_idx] =
481a88394cfSJeff Kirsher to_advert = tp->mii_advertise;
482a88394cfSJeff Kirsher } else if (tp->advertising[phy_idx]) {
483a88394cfSJeff Kirsher to_advert = tp->advertising[phy_idx];
484a88394cfSJeff Kirsher } else {
485a88394cfSJeff Kirsher tp->advertising[phy_idx] =
486a88394cfSJeff Kirsher tp->mii_advertise =
487a88394cfSJeff Kirsher to_advert = mii_advert;
488a88394cfSJeff Kirsher }
489a88394cfSJeff Kirsher
490a88394cfSJeff Kirsher tp->phys[phy_idx++] = phy;
491a88394cfSJeff Kirsher
492a88394cfSJeff Kirsher pr_info("tulip%d: MII transceiver #%d config %04x status %04x advertising %04x\n",
493a88394cfSJeff Kirsher board_idx, phy, mii_reg0, mii_status, mii_advert);
494a88394cfSJeff Kirsher
495a88394cfSJeff Kirsher /* Fixup for DLink with miswired PHY. */
496a88394cfSJeff Kirsher if (mii_advert != to_advert) {
497a88394cfSJeff Kirsher pr_debug("tulip%d: Advertising %04x on PHY %d, previously advertising %04x\n",
498a88394cfSJeff Kirsher board_idx, to_advert, phy, mii_advert);
499a88394cfSJeff Kirsher tulip_mdio_write (dev, phy, 4, to_advert);
500a88394cfSJeff Kirsher }
501a88394cfSJeff Kirsher
502a88394cfSJeff Kirsher /* Enable autonegotiation: some boards default to off. */
503a88394cfSJeff Kirsher if (tp->default_port == 0) {
504a88394cfSJeff Kirsher new_bmcr = mii_reg0 | BMCR_ANENABLE;
505a88394cfSJeff Kirsher if (new_bmcr != mii_reg0) {
506a88394cfSJeff Kirsher new_bmcr |= BMCR_ANRESTART;
507a88394cfSJeff Kirsher ane_switch = 1;
508a88394cfSJeff Kirsher }
509a88394cfSJeff Kirsher }
510a88394cfSJeff Kirsher /* ...or disable nway, if forcing media */
511a88394cfSJeff Kirsher else {
512a88394cfSJeff Kirsher new_bmcr = mii_reg0 & ~BMCR_ANENABLE;
513a88394cfSJeff Kirsher if (new_bmcr != mii_reg0)
514a88394cfSJeff Kirsher ane_switch = 1;
515a88394cfSJeff Kirsher }
516a88394cfSJeff Kirsher
517a88394cfSJeff Kirsher /* clear out bits we never want at this point */
518a88394cfSJeff Kirsher new_bmcr &= ~(BMCR_CTST | BMCR_FULLDPLX | BMCR_ISOLATE |
519a88394cfSJeff Kirsher BMCR_PDOWN | BMCR_SPEED100 | BMCR_LOOPBACK |
520a88394cfSJeff Kirsher BMCR_RESET);
521a88394cfSJeff Kirsher
522a88394cfSJeff Kirsher if (tp->full_duplex)
523a88394cfSJeff Kirsher new_bmcr |= BMCR_FULLDPLX;
524a88394cfSJeff Kirsher if (tulip_media_cap[tp->default_port] & MediaIs100)
525a88394cfSJeff Kirsher new_bmcr |= BMCR_SPEED100;
526a88394cfSJeff Kirsher
527a88394cfSJeff Kirsher if (new_bmcr != mii_reg0) {
528a88394cfSJeff Kirsher /* some phys need the ANE switch to
529a88394cfSJeff Kirsher * happen before forced media settings
530a88394cfSJeff Kirsher * will "take." However, we write the
531a88394cfSJeff Kirsher * same value twice in order not to
532a88394cfSJeff Kirsher * confuse the sane phys.
533a88394cfSJeff Kirsher */
534a88394cfSJeff Kirsher if (ane_switch) {
535a88394cfSJeff Kirsher tulip_mdio_write (dev, phy, MII_BMCR, new_bmcr);
536a88394cfSJeff Kirsher udelay (10);
537a88394cfSJeff Kirsher }
538a88394cfSJeff Kirsher tulip_mdio_write (dev, phy, MII_BMCR, new_bmcr);
539a88394cfSJeff Kirsher }
540a88394cfSJeff Kirsher }
541a88394cfSJeff Kirsher tp->mii_cnt = phy_idx;
542a88394cfSJeff Kirsher if (tp->mtable && tp->mtable->has_mii && phy_idx == 0) {
543a88394cfSJeff Kirsher pr_info("tulip%d: ***WARNING***: No MII transceiver found!\n",
544a88394cfSJeff Kirsher board_idx);
545a88394cfSJeff Kirsher tp->phys[0] = 1;
546a88394cfSJeff Kirsher }
547a88394cfSJeff Kirsher }
548