xref: /linux/drivers/net/ethernet/dec/tulip/media.c (revision 17bd3a1e)
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