| Ben Hutchings | 8ceee66 | 2008-04-27 12:55:59 +0100 | [diff] [blame] | 1 | /**************************************************************************** | 
 | 2 |  * Driver for Solarflare Solarstorm network controllers and boards | 
 | 3 |  * Copyright 2005-2006 Fen Systems Ltd. | 
 | 4 |  * Copyright 2006 Solarflare Communications Inc. | 
 | 5 |  * | 
 | 6 |  * This program is free software; you can redistribute it and/or modify it | 
 | 7 |  * under the terms of the GNU General Public License version 2 as published | 
 | 8 |  * by the Free Software Foundation, incorporated herein by reference. | 
 | 9 |  */ | 
 | 10 |  | 
 | 11 | #ifndef EFX_GMII_H | 
 | 12 | #define EFX_GMII_H | 
 | 13 |  | 
 | 14 | /* | 
 | 15 |  * GMII interface | 
 | 16 |  */ | 
 | 17 |  | 
 | 18 | #include <linux/mii.h> | 
 | 19 |  | 
 | 20 | /* GMII registers, excluding registers already defined as MII | 
 | 21 |  * registers in mii.h | 
 | 22 |  */ | 
 | 23 | #define GMII_IER		0x12	/* Interrupt enable register */ | 
 | 24 | #define GMII_ISR		0x13	/* Interrupt status register */ | 
 | 25 |  | 
 | 26 | /* Interrupt enable register */ | 
 | 27 | #define IER_ANEG_ERR		0x8000	/* Bit 15 - autonegotiation error */ | 
 | 28 | #define IER_SPEED_CHG		0x4000	/* Bit 14 - speed changed */ | 
 | 29 | #define IER_DUPLEX_CHG		0x2000	/* Bit 13 - duplex changed */ | 
 | 30 | #define IER_PAGE_RCVD		0x1000	/* Bit 12 - page received */ | 
 | 31 | #define IER_ANEG_DONE		0x0800	/* Bit 11 - autonegotiation complete */ | 
 | 32 | #define IER_LINK_CHG		0x0400	/* Bit 10 - link status changed */ | 
 | 33 | #define IER_SYM_ERR		0x0200	/* Bit 9 - symbol error */ | 
 | 34 | #define IER_FALSE_CARRIER	0x0100	/* Bit 8 - false carrier */ | 
 | 35 | #define IER_FIFO_ERR		0x0080	/* Bit 7 - FIFO over/underflow */ | 
 | 36 | #define IER_MDIX_CHG		0x0040	/* Bit 6 - MDI crossover changed */ | 
 | 37 | #define IER_DOWNSHIFT		0x0020	/* Bit 5 - downshift */ | 
 | 38 | #define IER_ENERGY		0x0010	/* Bit 4 - energy detect */ | 
 | 39 | #define IER_DTE_POWER		0x0004	/* Bit 2 - DTE power detect */ | 
 | 40 | #define IER_POLARITY_CHG	0x0002	/* Bit 1 - polarity changed */ | 
 | 41 | #define IER_JABBER		0x0001	/* Bit 0 - jabber */ | 
 | 42 |  | 
 | 43 | /* Interrupt status register */ | 
 | 44 | #define ISR_ANEG_ERR		0x8000	/* Bit 15 - autonegotiation error */ | 
 | 45 | #define ISR_SPEED_CHG		0x4000	/* Bit 14 - speed changed */ | 
 | 46 | #define ISR_DUPLEX_CHG		0x2000	/* Bit 13 - duplex changed */ | 
 | 47 | #define ISR_PAGE_RCVD		0x1000	/* Bit 12 - page received */ | 
 | 48 | #define ISR_ANEG_DONE		0x0800	/* Bit 11 - autonegotiation complete */ | 
 | 49 | #define ISR_LINK_CHG		0x0400	/* Bit 10 - link status changed */ | 
 | 50 | #define ISR_SYM_ERR		0x0200	/* Bit 9 - symbol error */ | 
 | 51 | #define ISR_FALSE_CARRIER	0x0100	/* Bit 8 - false carrier */ | 
 | 52 | #define ISR_FIFO_ERR		0x0080	/* Bit 7 - FIFO over/underflow */ | 
 | 53 | #define ISR_MDIX_CHG		0x0040	/* Bit 6 - MDI crossover changed */ | 
 | 54 | #define ISR_DOWNSHIFT		0x0020	/* Bit 5 - downshift */ | 
 | 55 | #define ISR_ENERGY		0x0010	/* Bit 4 - energy detect */ | 
 | 56 | #define ISR_DTE_POWER		0x0004	/* Bit 2 - DTE power detect */ | 
 | 57 | #define ISR_POLARITY_CHG	0x0002	/* Bit 1 - polarity changed */ | 
 | 58 | #define ISR_JABBER		0x0001	/* Bit 0 - jabber */ | 
 | 59 |  | 
 | 60 | /* Logically extended advertisement register */ | 
 | 61 | #define GM_ADVERTISE_SLCT		ADVERTISE_SLCT | 
 | 62 | #define GM_ADVERTISE_CSMA		ADVERTISE_CSMA | 
 | 63 | #define GM_ADVERTISE_10HALF		ADVERTISE_10HALF | 
 | 64 | #define GM_ADVERTISE_1000XFULL		ADVERTISE_1000XFULL | 
 | 65 | #define GM_ADVERTISE_10FULL		ADVERTISE_10FULL | 
 | 66 | #define GM_ADVERTISE_1000XHALF		ADVERTISE_1000XHALF | 
 | 67 | #define GM_ADVERTISE_100HALF		ADVERTISE_100HALF | 
 | 68 | #define GM_ADVERTISE_1000XPAUSE		ADVERTISE_1000XPAUSE | 
 | 69 | #define GM_ADVERTISE_100FULL		ADVERTISE_100FULL | 
 | 70 | #define GM_ADVERTISE_1000XPSE_ASYM	ADVERTISE_1000XPSE_ASYM | 
 | 71 | #define GM_ADVERTISE_100BASE4		ADVERTISE_100BASE4 | 
 | 72 | #define GM_ADVERTISE_PAUSE_CAP		ADVERTISE_PAUSE_CAP | 
 | 73 | #define GM_ADVERTISE_PAUSE_ASYM		ADVERTISE_PAUSE_ASYM | 
 | 74 | #define GM_ADVERTISE_RESV		ADVERTISE_RESV | 
 | 75 | #define GM_ADVERTISE_RFAULT		ADVERTISE_RFAULT | 
 | 76 | #define GM_ADVERTISE_LPACK		ADVERTISE_LPACK | 
 | 77 | #define GM_ADVERTISE_NPAGE		ADVERTISE_NPAGE | 
 | 78 | #define GM_ADVERTISE_1000FULL		(ADVERTISE_1000FULL << 8) | 
 | 79 | #define GM_ADVERTISE_1000HALF		(ADVERTISE_1000HALF << 8) | 
 | 80 | #define GM_ADVERTISE_1000		(GM_ADVERTISE_1000FULL | \ | 
 | 81 | 					 GM_ADVERTISE_1000HALF) | 
 | 82 | #define GM_ADVERTISE_FULL		(GM_ADVERTISE_1000FULL | \ | 
 | 83 | 					 ADVERTISE_FULL) | 
 | 84 | #define GM_ADVERTISE_ALL		(GM_ADVERTISE_1000FULL | \ | 
 | 85 | 					 GM_ADVERTISE_1000HALF | \ | 
 | 86 | 					 ADVERTISE_ALL) | 
 | 87 |  | 
 | 88 | /* Logically extended link partner ability register */ | 
 | 89 | #define GM_LPA_SLCT			LPA_SLCT | 
 | 90 | #define GM_LPA_10HALF			LPA_10HALF | 
 | 91 | #define GM_LPA_1000XFULL		LPA_1000XFULL | 
 | 92 | #define GM_LPA_10FULL			LPA_10FULL | 
 | 93 | #define GM_LPA_1000XHALF		LPA_1000XHALF | 
 | 94 | #define GM_LPA_100HALF			LPA_100HALF | 
 | 95 | #define GM_LPA_1000XPAUSE		LPA_1000XPAUSE | 
 | 96 | #define GM_LPA_100FULL			LPA_100FULL | 
 | 97 | #define GM_LPA_1000XPAUSE_ASYM		LPA_1000XPAUSE_ASYM | 
 | 98 | #define GM_LPA_100BASE4			LPA_100BASE4 | 
 | 99 | #define GM_LPA_PAUSE_CAP		LPA_PAUSE_CAP | 
 | 100 | #define GM_LPA_PAUSE_ASYM		LPA_PAUSE_ASYM | 
 | 101 | #define GM_LPA_RESV			LPA_RESV | 
 | 102 | #define GM_LPA_RFAULT			LPA_RFAULT | 
 | 103 | #define GM_LPA_LPACK			LPA_LPACK | 
 | 104 | #define GM_LPA_NPAGE			LPA_NPAGE | 
 | 105 | #define GM_LPA_1000FULL			(LPA_1000FULL << 6) | 
 | 106 | #define GM_LPA_1000HALF			(LPA_1000HALF << 6) | 
 | 107 | #define GM_LPA_10000FULL		0x00040000 | 
 | 108 | #define GM_LPA_10000HALF		0x00080000 | 
 | 109 | #define GM_LPA_DUPLEX			(GM_LPA_1000FULL | GM_LPA_10000FULL \ | 
 | 110 | 					 | LPA_DUPLEX) | 
 | 111 | #define GM_LPA_10			(LPA_10FULL | LPA_10HALF) | 
 | 112 | #define GM_LPA_100			LPA_100 | 
 | 113 | #define GM_LPA_1000			(GM_LPA_1000FULL | GM_LPA_1000HALF) | 
 | 114 | #define GM_LPA_10000			(GM_LPA_10000FULL | GM_LPA_10000HALF) | 
 | 115 |  | 
 | 116 | /* Retrieve GMII autonegotiation advertised abilities | 
 | 117 |  * | 
 | 118 |  * The MII advertisment register (MII_ADVERTISE) is logically extended | 
 | 119 |  * to include advertisement bits ADVERTISE_1000FULL and | 
 | 120 |  * ADVERTISE_1000HALF from MII_CTRL1000.  The result can be tested | 
 | 121 |  * against the GM_ADVERTISE_xxx constants. | 
 | 122 |  */ | 
 | 123 | static inline unsigned int gmii_advertised(struct mii_if_info *gmii) | 
 | 124 | { | 
 | 125 | 	unsigned int advertise; | 
 | 126 | 	unsigned int ctrl1000; | 
 | 127 |  | 
 | 128 | 	advertise = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_ADVERTISE); | 
 | 129 | 	ctrl1000 = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_CTRL1000); | 
 | 130 | 	return (((ctrl1000 << 8) & GM_ADVERTISE_1000) | advertise); | 
 | 131 | } | 
 | 132 |  | 
 | 133 | /* Retrieve GMII autonegotiation link partner abilities | 
 | 134 |  * | 
 | 135 |  * The MII link partner ability register (MII_LPA) is logically | 
 | 136 |  * extended by adding bits LPA_1000HALF and LPA_1000FULL from | 
 | 137 |  * MII_STAT1000.  The result can be tested against the GM_LPA_xxx | 
 | 138 |  * constants. | 
 | 139 |  */ | 
 | 140 | static inline unsigned int gmii_lpa(struct mii_if_info *gmii) | 
 | 141 | { | 
 | 142 | 	unsigned int lpa; | 
 | 143 | 	unsigned int stat1000; | 
 | 144 |  | 
 | 145 | 	lpa = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_LPA); | 
 | 146 | 	stat1000 = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_STAT1000); | 
 | 147 | 	return (((stat1000 << 6) & GM_LPA_1000) | lpa); | 
 | 148 | } | 
 | 149 |  | 
 | 150 | /* Calculate GMII autonegotiated link technology | 
 | 151 |  * | 
 | 152 |  * "negotiated" should be the result of gmii_advertised() logically | 
 | 153 |  * ANDed with the result of gmii_lpa(). | 
 | 154 |  * | 
 | 155 |  * "tech" will be negotiated with the unused bits masked out.  For | 
 | 156 |  * example, if both ends of the link are capable of both | 
 | 157 |  * GM_LPA_1000FULL and GM_LPA_100FULL, GM_LPA_100FULL will be masked | 
 | 158 |  * out. | 
 | 159 |  */ | 
 | 160 | static inline unsigned int gmii_nway_result(unsigned int negotiated) | 
 | 161 | { | 
 | 162 | 	unsigned int other_bits; | 
 | 163 |  | 
 | 164 | 	/* Mask out the speed and duplexity bits */ | 
 | 165 | 	other_bits = negotiated & ~(GM_LPA_10 | GM_LPA_100 | GM_LPA_1000); | 
 | 166 |  | 
 | 167 | 	if (negotiated & GM_LPA_1000FULL) | 
 | 168 | 		return (other_bits | GM_LPA_1000FULL); | 
 | 169 | 	else if (negotiated & GM_LPA_1000HALF) | 
 | 170 | 		return (other_bits | GM_LPA_1000HALF); | 
 | 171 | 	else | 
 | 172 | 		return (other_bits | mii_nway_result(negotiated)); | 
 | 173 | } | 
 | 174 |  | 
 | 175 | /* Calculate GMII non-autonegotiated link technology | 
 | 176 |  * | 
 | 177 |  * This provides an equivalent to gmii_nway_result for the case when | 
 | 178 |  * autonegotiation is disabled. | 
 | 179 |  */ | 
 | 180 | static inline unsigned int gmii_forced_result(unsigned int bmcr) | 
 | 181 | { | 
 | 182 | 	unsigned int result; | 
 | 183 | 	int full_duplex; | 
 | 184 |  | 
 | 185 | 	full_duplex = bmcr & BMCR_FULLDPLX; | 
 | 186 | 	if (bmcr & BMCR_SPEED1000) | 
 | 187 | 		result = full_duplex ? GM_LPA_1000FULL : GM_LPA_1000HALF; | 
 | 188 | 	else if (bmcr & BMCR_SPEED100) | 
 | 189 | 		result = full_duplex ? GM_LPA_100FULL : GM_LPA_100HALF; | 
 | 190 | 	else | 
 | 191 | 		result = full_duplex ? GM_LPA_10FULL : GM_LPA_10HALF; | 
 | 192 | 	return result; | 
 | 193 | } | 
 | 194 |  | 
 | 195 | #endif /* EFX_GMII_H */ |