History

net: phylink: pcs: add 802.3 clause 22 helpers

Implement helpers for PCS accessed via the MII bus using 802.3 clause 22 cycles, conforming to 802.3 clause 37 and Cisco SGMII specifications for the advertisement word.

Russell King committed 6 years ago

Commit 74db1c11 parent 6cc7cf83 files · +217 −0Browse files

Unified · Split

3 files
  1. drivers/net/phy/phylink.c +206 −0
  2. include/linux/phylink.h +6 −0
  3. include/uapi/linux/mii.h +5 −0
drivers/net/phy/phylink.c+206−0
@@ -2068,4 +2068,210 @@ void phylink_helper_basex_speed(struct phylink_link_state *state) · 2067 unmodified lines
20682068 }
20692069 EXPORT_SYMBOL_GPL(phylink_helper_basex_speed);
20702070
2071+static void phylink_decode_c37_word(struct phylink_link_state *state,
2072+ uint16_t config_reg, int speed)
2073+{
2074+ bool tx_pause, rx_pause;
2075+ int fd_bit;
2076+
2077+ if (speed == SPEED_2500)
2078+ fd_bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT;
2079+ else
2080+ fd_bit = ETHTOOL_LINK_MODE_1000baseX_Full_BIT;
2081+
2082+ mii_lpa_mod_linkmode_x(state->lp_advertising, config_reg, fd_bit);
2083+
2084+ if (linkmode_test_bit(fd_bit, state->advertising) &&
2085+ linkmode_test_bit(fd_bit, state->lp_advertising)) {
2086+ state->speed = speed;
2087+ state->duplex = DUPLEX_FULL;
2088+ } else {
2089+ /* negotiation failure */
2090+ state->link = false;
2091+ }
2092+
2093+ linkmode_resolve_pause(state->advertising, state->lp_advertising,
2094+ &tx_pause, &rx_pause);
2095+
2096+ if (tx_pause)
2097+ state->pause |= MLO_PAUSE_TX;
2098+ if (rx_pause)
2099+ state->pause |= MLO_PAUSE_RX;
2100+}
2101+
2102+static void phylink_decode_sgmii_word(struct phylink_link_state *state,
2103+ uint16_t config_reg)
2104+{
2105+ if (!(config_reg & LPA_SGMII_LINK)) {
2106+ state->link = false;
2107+ return;
2108+ }
2109+
2110+ switch (config_reg & LPA_SGMII_SPD_MASK) {
2111+ case LPA_SGMII_10:
2112+ state->speed = SPEED_10;
2113+ break;
2114+ case LPA_SGMII_100:
2115+ state->speed = SPEED_100;
2116+ break;
2117+ case LPA_SGMII_1000:
2118+ state->speed = SPEED_1000;
2119+ break;
2120+ default:
2121+ state->link = false;
2122+ return;
2123+ }
2124+ if (config_reg & LPA_SGMII_FULL_DUPLEX)
2125+ state->duplex = DUPLEX_FULL;
2126+ else
2127+ state->duplex = DUPLEX_HALF;
2128+}
2129+
2130+/**
2131+ * phylink_mii_c22_pcs_get_state() - read the MAC PCS state
2132+ * @pcs: a pointer to a &struct mdio_device.
2133+ * @state: a pointer to a &struct phylink_link_state.
2134+ *
2135+ * Helper for MAC PCS supporting the 802.3 clause 22 register set for
2136+ * clause 37 negotiation and/or SGMII control.
2137+ *
2138+ * Read the MAC PCS state from the MII device configured in @config and
2139+ * parse the Clause 37 or Cisco SGMII link partner negotiation word into
2140+ * the phylink @state structure. This is suitable to be directly plugged
2141+ * into the mac_pcs_get_state() member of the struct phylink_mac_ops
2142+ * structure.
2143+ */
2144+void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs,
2145+ struct phylink_link_state *state)
2146+{
2147+ struct mii_bus *bus = pcs->bus;
2148+ int addr = pcs->addr;
2149+ int bmsr, lpa;
2150+
2151+ bmsr = mdiobus_read(bus, addr, MII_BMSR);
2152+ lpa = mdiobus_read(bus, addr, MII_LPA);
2153+ if (bmsr < 0 || lpa < 0) {
2154+ state->link = false;
2155+ return;
2156+ }
2157+
2158+ state->link = !!(bmsr & BMSR_LSTATUS);
2159+ state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE);
2160+ if (!state->link)
2161+ return;
2162+
2163+ switch (state->interface) {
2164+ case PHY_INTERFACE_MODE_1000BASEX:
2165+ phylink_decode_c37_word(state, lpa, SPEED_1000);
2166+ break;
2167+
2168+ case PHY_INTERFACE_MODE_2500BASEX:
2169+ phylink_decode_c37_word(state, lpa, SPEED_2500);
2170+ break;
2171+
2172+ case PHY_INTERFACE_MODE_SGMII:
2173+ phylink_decode_sgmii_word(state, lpa);
2174+ break;
2175+
2176+ default:
2177+ state->link = false;
2178+ break;
2179+ }
2180+}
2181+EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_get_state);
2182+
2183+/**
2184+ * phylink_mii_c22_pcs_set_advertisement() - configure the clause 37 PCS
2185+ * advertisement
2186+ * @pcs: a pointer to a &struct mdio_device.
2187+ * @state: a pointer to the state being configured.
2188+ *
2189+ * Helper for MAC PCS supporting the 802.3 clause 22 register set for
2190+ * clause 37 negotiation and/or SGMII control.
2191+ *
2192+ * Configure the clause 37 PCS advertisement as specified by @state. This
2193+ * does not trigger a renegotiation; phylink will do that via the
2194+ * mac_an_restart() method of the struct phylink_mac_ops structure.
2195+ *
2196+ * Returns negative error code on failure to configure the advertisement,
2197+ * zero if no change has been made, or one if the advertisement has changed.
2198+ */
2199+int phylink_mii_c22_pcs_set_advertisement(struct mdio_device *pcs,
2200+ const struct phylink_link_state *state)
2201+{
2202+ struct mii_bus *bus = pcs->bus;
2203+ int addr = pcs->addr;
2204+ int val, ret;
2205+ u16 adv;
2206+
2207+ switch (state->interface) {
2208+ case PHY_INTERFACE_MODE_1000BASEX:
2209+ case PHY_INTERFACE_MODE_2500BASEX:
2210+ adv = ADVERTISE_1000XFULL;
2211+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
2212+ state->advertising))
2213+ adv |= ADVERTISE_1000XPAUSE;
2214+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
2215+ state->advertising))
2216+ adv |= ADVERTISE_1000XPSE_ASYM;
2217+
2218+ val = mdiobus_read(bus, addr, MII_ADVERTISE);
2219+ if (val < 0)
2220+ return val;
2221+
2222+ if (val == adv)
2223+ return 0;
2224+
2225+ ret = mdiobus_write(bus, addr, MII_ADVERTISE, adv);
2226+ if (ret < 0)
2227+ return ret;
2228+
2229+ return 1;
2230+
2231+ case PHY_INTERFACE_MODE_SGMII:
2232+ val = mdiobus_read(bus, addr, MII_ADVERTISE);
2233+ if (val < 0)
2234+ return val;
2235+
2236+ if (val == 0x0001)
2237+ return 0;
2238+
2239+ ret = mdiobus_write(bus, addr, MII_ADVERTISE, 0x0001);
2240+ if (ret < 0)
2241+ return ret;
2242+
2243+ return 1;
2244+
2245+ default:
2246+ /* Nothing to do for other modes */
2247+ return 0;
2248+ }
2249+}
2250+EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_set_advertisement);
2251+
2252+/**
2253+ * phylink_mii_c22_pcs_an_restart() - restart 802.3z autonegotiation
2254+ * @pcs: a pointer to a &struct mdio_device.
2255+ *
2256+ * Helper for MAC PCS supporting the 802.3 clause 22 register set for
2257+ * clause 37 negotiation.
2258+ *
2259+ * Restart the clause 37 negotiation with the link partner. This is
2260+ * suitable to be directly plugged into the mac_pcs_get_state() member
2261+ * of the struct phylink_mac_ops structure.
2262+ */
2263+void phylink_mii_c22_pcs_an_restart(struct mdio_device *pcs)
2264+{
2265+ struct mii_bus *bus = pcs->bus;
2266+ int val, addr = pcs->addr;
2267+
2268+ val = mdiobus_read(bus, addr, MII_BMCR);
2269+ if (val >= 0) {
2270+ val |= BMCR_ANRESTART;
2271+
2272+ mdiobus_write(bus, addr, MII_BMCR, val);
2273+ }
2274+}
2275+EXPORT_SYMBOL_GPL(phylink_mii_c22_pcs_an_restart);
2276+
20712277 MODULE_LICENSE("GPL v2");
include/linux/phylink.h+6−0
@@ -317,4 +317,10 @@ int phylink_mii_ioctl(struct phylink *, struct ifreq *, int); · 316 unmodified lines
317317 void phylink_set_port_modes(unsigned long *bits);
318318 void phylink_helper_basex_speed(struct phylink_link_state *state);
319319
320+void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs,
321+ struct phylink_link_state *state);
322+int phylink_mii_c22_pcs_set_advertisement(struct mdio_device *pcs,
323+ const struct phylink_link_state *state);
324+void phylink_mii_c22_pcs_an_restart(struct mdio_device *pcs);
325+
320326 #endif
include/uapi/linux/mii.h+5−0
@@ -134,11 +134,16 @@ · 133 unmodified lines
134134 /* MAC and PHY tx_config_Reg[15:0] for SGMII in-band auto-negotiation.*/
135135 #define ADVERTISE_SGMII 0x0001 /* MAC can do SGMII */
136136 #define LPA_SGMII 0x0001 /* PHY can do SGMII */
137+#define LPA_SGMII_SPD_MASK 0x0c00 /* SGMII speed mask */
138+#define LPA_SGMII_FULL_DUPLEX 0x1000 /* SGMII full duplex */
137139 #define LPA_SGMII_DPX_SPD_MASK 0x1C00 /* SGMII duplex and speed bits */
140+#define LPA_SGMII_10 0x0000 /* 10Mbps */
138141 #define LPA_SGMII_10HALF 0x0000 /* Can do 10mbps half-duplex */
139142 #define LPA_SGMII_10FULL 0x1000 /* Can do 10mbps full-duplex */
143+#define LPA_SGMII_100 0x0400 /* 100Mbps */
140144 #define LPA_SGMII_100HALF 0x0400 /* Can do 100mbps half-duplex */
141145 #define LPA_SGMII_100FULL 0x1400 /* Can do 100mbps full-duplex */
146+#define LPA_SGMII_1000 0x0800 /* 1000Mbps */
142147 #define LPA_SGMII_1000HALF 0x0800 /* Can do 1000mbps half-duplex */
143148 #define LPA_SGMII_1000FULL 0x1800 /* Can do 1000mbps full-duplex */
144149 #define LPA_SGMII_LINK 0x8000 /* PHY link with copper-side partner */