/* Represents 1ppm adjustment in 2^32 format with * each nsec contains 4 clock cycles. * The value is calculated as following: (1/1000000)/((2^-32)/4)
*/ #define LAN8814_1PPM_FORMAT 17179
/* Represents 1ppm adjustment in 2^32 format with * each nsec contains 8 clock cycles. * The value is calculated as following: (1/1000000)/((2^-32)/8)
*/ #define LAN8841_1PPM_FORMAT 34360
temp &= ~(3 << shift);
temp |= val << shift;
rc = phy_write(phydev, reg, temp);
out: if (rc < 0)
phydev_err(phydev, "failed to set led mode\n");
return rc;
}
/* Disable PHY address 0 as the broadcast address, so that it can be used as a * unique (non-broadcast) address on a shared bus.
*/ staticint kszphy_broadcast_disable(struct phy_device *phydev)
{ int ret;
ret = phy_read(phydev, MII_KSZPHY_OMSO); if (ret < 0) goto out;
ret = phy_write(phydev, MII_KSZPHY_OMSO, ret | KSZPHY_OMSO_B_CAST_OFF);
out: if (ret)
phydev_err(phydev, "failed to disable broadcast address\n");
return ret;
}
staticint kszphy_nand_tree_disable(struct phy_device *phydev)
{ int ret;
ret = phy_read(phydev, MII_KSZPHY_OMSO); if (ret < 0) goto out;
if (!(ret & KSZPHY_OMSO_NAND_TREE_ON)) return 0;
ret = phy_write(phydev, MII_KSZPHY_OMSO,
ret & ~KSZPHY_OMSO_NAND_TREE_ON);
out: if (ret)
phydev_err(phydev, "failed to disable NAND tree mode\n");
return ret;
}
/* Some config bits need to be set again on resume, handle them here. */ staticint kszphy_config_reset(struct phy_device *phydev)
{ struct kszphy_priv *priv = phydev->priv; int ret;
if (priv->rmii_ref_clk_sel) {
ret = kszphy_rmii_clk_sel(phydev, priv->rmii_ref_clk_sel_val); if (ret) {
phydev_err(phydev, "failed to set rmii reference clock\n"); return ret;
}
}
if (priv->type && priv->led_mode >= 0)
kszphy_setup_led(phydev, priv->type->led_mode_reg, priv->led_mode);
staticint ksz8051_ksz8795_match_phy_device(struct phy_device *phydev, constbool ksz_8051)
{ int ret;
if (!phy_id_compare(phydev->phy_id, PHY_ID_KSZ8051, MICREL_PHY_ID_MASK)) return 0;
ret = phy_read(phydev, MII_BMSR); if (ret < 0) return ret;
/* KSZ8051 PHY and KSZ8794/KSZ8795/KSZ8765 switch share the same * exact PHY ID. However, they can be told apart by the extended * capability registers presence. The KSZ8051 PHY has them while * the switch does not.
*/
ret &= BMSR_ERCAP; if (ksz_8051) return ret; else return !ret;
}
staticint ksz8081_config_init(struct phy_device *phydev)
{ /* KSZPHY_OMSO_FACTORY_TEST is set at de-assertion of the reset line * based on the RXER (KSZ8081RNA/RND) or TXC (KSZ8081MNX/RNB) pin. If a * pull-down is missing, the factory test mode should be cleared by * manually writing a 0.
*/
phy_clear_bits(phydev, MII_KSZPHY_OMSO, KSZPHY_OMSO_FACTORY_TEST);
switch (ctrl) { case ETH_TP_MDI:
val = KSZ8081_CTRL2_DISABLE_AUTO_MDIX; break; case ETH_TP_MDI_X:
val = KSZ8081_CTRL2_DISABLE_AUTO_MDIX |
KSZ8081_CTRL2_MDI_MDI_X_SELECT; break; case ETH_TP_MDI_AUTO:
val = 0; break; default: return 0;
}
staticint ksz8081_config_aneg(struct phy_device *phydev)
{ int ret;
ret = genphy_config_aneg(phydev); if (ret) return ret;
/* The MDI-X configuration is automatically changed by the PHY after * switching from autoneg off to on. So, take MDI-X configuration under * own control and set it after autoneg configuration was done.
*/ return ksz8081_config_mdix(phydev, phydev->mdix_ctrl);
}
staticint ksz8081_mdix_update(struct phy_device *phydev)
{ int ret;
ret = phy_read(phydev, MII_KSZPHY_CTRL_2); if (ret < 0) return ret;
staticint ksz8081_read_status(struct phy_device *phydev)
{ int ret;
ret = ksz8081_mdix_update(phydev); if (ret < 0) return ret;
return genphy_read_status(phydev);
}
staticint ksz8061_config_init(struct phy_device *phydev)
{ int ret;
/* Chip can be powered down by the bootstrap code. */
ret = phy_read(phydev, MII_BMCR); if (ret < 0) return ret; if (ret & BMCR_PDOWN) {
ret = phy_write(phydev, MII_BMCR, ret & ~BMCR_PDOWN); if (ret < 0) return ret;
usleep_range(1000, 2000);
}
ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_DEVID1, 0xB61A); if (ret) return ret;
/* The Micrel driver has a deprecated option to place phy OF * properties in the MAC node. Walk up the tree of devices to * find a device with an OF node.
*/
dev_walker = &phydev->mdio.dev; do {
of_node = dev_walker->of_node;
dev_walker = dev_walker->parent;
/* KSZ9031 has internal RGMII_IDRX = 1.2ns and RGMII_IDTX = 0ns. To * provide different RGMII options we need to configure delay offset * for each pad relative to build in delay.
*/ /* keep rx as "No delay adjustment" and set rx_clk to +0.60ns to get delays of * 1.80ns
*/ #define RX_ID 0x7 #define RX_CLK_ID 0x19
/* set rx to +0.30ns and rx_clk to -0.90ns to compensate the * internal 1.2ns delay.
*/ #define RX_ND 0xc #define RX_CLK_ND 0x0
/* set tx to -0.42ns and tx_clk to +0.96ns to get 1.38ns delay */ #define TX_ID 0x0 #define TX_CLK_ID 0x1f
/* set tx and tx_clk to "No delay adjustment" to keep 0ns * dealy
*/ #define TX_ND 0x7 #define TX_CLK_ND 0xf
result = ksz9031_enable_edpd(phydev); if (result < 0) return result;
/* The Micrel driver has a deprecated option to place phy OF * properties in the MAC node. Walk up the tree of devices to * find a device with an OF node.
*/
dev_walker = &phydev->mdio.dev; do {
of_node = dev_walker->of_node;
dev_walker = dev_walker->parent;
} while (!of_node && dev_walker);
if (of_node) { bool update = false;
if (phy_interface_is_rgmii(phydev)) {
result = ksz9031_config_rgmii_delay(phydev); if (result < 0) return result;
}
if (update && !phy_interface_is_rgmii(phydev))
phydev_warn(phydev, "*-skew-ps values should be used only with RGMII PHY modes\n");
/* Silicon Errata Sheet (DS80000691D or DS80000692D): * When the device links in the 1000BASE-T slave mode only, * the optional 125MHz reference output clock (CLK125_NDO) * has wide duty cycle variation. * * The optional CLK125_NDO clock does not meet the RGMII * 45/55 percent (min/max) duty cycle requirement and therefore * cannot be used directly by the MAC side for clocking * applications that have setup/hold time requirements on * rising and falling clock edges. * * Workaround: * Force the phy to be the master to receive a stable clock * which meets the duty cycle requirement.
*/ if (of_property_read_bool(of_node, "micrel,force-master")) {
result = phy_read(phydev, MII_CTRL1000); if (result < 0) goto err_force_master;
/* enable master mode, config & prefer master */
result |= CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER;
result = phy_write(phydev, MII_CTRL1000, result); if (result < 0) goto err_force_master;
}
}
return ksz9031_center_flp_timing(phydev);
err_force_master:
phydev_err(phydev, "failed to force the phy to master mode\n"); return result;
}
/* Silicon Errata DS80000693B * * When LEDs are configured in Individual Mode, LED1 is ON in a no-link * condition. Workaround is to set register 0x1e, bit 9, this way LED1 behaves * according to the datasheet (off if there is no link).
*/ staticint ksz9131_led_errata(struct phy_device *phydev)
{ int reg;
switch (ctrl) { case ETH_TP_MDI:
val = MII_KSZ9131_AUTO_MDIX_SWAP_OFF |
MII_KSZ9131_AUTO_MDI_SET; break; case ETH_TP_MDI_X:
val = MII_KSZ9131_AUTO_MDIX_SWAP_OFF; break; case ETH_TP_MDI_AUTO:
val = 0; break; default: return 0;
}
staticint ksz9131_read_status(struct phy_device *phydev)
{ int ret;
ret = ksz9131_mdix_update(phydev); if (ret < 0) return ret;
return genphy_read_status(phydev);
}
staticint ksz9131_config_aneg(struct phy_device *phydev)
{ int ret;
ret = ksz9131_config_mdix(phydev, phydev->mdix_ctrl); if (ret) return ret;
return genphy_config_aneg(phydev);
}
staticint ksz9477_get_features(struct phy_device *phydev)
{ int ret;
ret = genphy_read_abilities(phydev); if (ret) return ret;
/* The "EEE control and capability 1" (Register 3.20) seems to be * influenced by the "EEE advertisement 1" (Register 7.60). Changes * on the 7.60 will affect 3.20. So, we need to construct our own list * of caps. * KSZ8563R should have 100BaseTX/Full only.
*/
linkmode_and(phydev->supported_eee, phydev->supported,
PHY_EEE_CAP1_FEATURES);
staticint ksz9031_get_features(struct phy_device *phydev)
{ int ret;
ret = genphy_read_abilities(phydev); if (ret < 0) return ret;
/* Silicon Errata Sheet (DS80000691D or DS80000692D): * Whenever the device's Asymmetric Pause capability is set to 1, * link-up may fail after a link-up to link-down transition. * * The Errata Sheet is for ksz9031, but ksz9021 has the same issue * * Workaround: * Do not enable the Asymmetric Pause capability bit.
*/
linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->supported);
/* We force setting the Pause capability as the core will force the * Asymmetric Pause capability to 1 otherwise.
*/
linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->supported);
return 0;
}
staticint ksz9031_read_status(struct phy_device *phydev)
{ int err; int regval;
err = genphy_read_status(phydev); if (err) return err;
/* Make sure the PHY is not broken. Read idle error count, * and reset the PHY if it is maxed out.
*/
regval = phy_read(phydev, MII_STAT1000); if ((regval & 0xFF) == 0xFF) {
phy_init_hw(phydev);
phydev->link = 0; if (phydev->drv->config_intr && phy_interrupt_is_valid(phydev))
phydev->drv->config_intr(phydev); return genphy_config_aneg(phydev);
}
/* KSZ9131RNX, DS00002841B-page 38, 4.14 LinkMD (R) Cable Diagnostic * Prior to running the cable diagnostics, Auto-negotiation should * be disabled, full duplex set and the link speed set to 1000Mbps * via the Basic Control Register.
*/
ret = phy_modify(phydev, MII_BMCR,
BMCR_SPEED1000 | BMCR_FULLDPLX |
BMCR_ANENABLE | BMCR_SPEED100,
BMCR_SPEED1000 | BMCR_FULLDPLX); if (ret) return ret;
/* KSZ9131RNX, DS00002841B-page 38, 4.14 LinkMD (R) Cable Diagnostic * The Master-Slave configuration should be set to Slave by writing * a value of 0x1000 to the Auto-Negotiation Master Slave Control * Register.
*/
ret = phy_read(phydev, MII_CTRL1000); if (ret < 0) return ret;
/* Cache these bits, they need to be restored once LinkMD finishes. */
priv->vct_ctrl1000 = ret & (CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER);
ret &= ~(CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER);
ret |= CTL1000_ENABLE_MASTER;
return phy_write(phydev, MII_CTRL1000, ret);
}
staticint ksz9x31_cable_test_result_trans(u16 status)
{ switch (FIELD_GET(KSZ9x31_LMD_VCT_ST_MASK, status)) { case KSZ9x31_LMD_VCT_ST_NORMAL: return ETHTOOL_A_CABLE_RESULT_CODE_OK; case KSZ9x31_LMD_VCT_ST_OPEN: return ETHTOOL_A_CABLE_RESULT_CODE_OPEN; case KSZ9x31_LMD_VCT_ST_SHORT: return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT; case KSZ9x31_LMD_VCT_ST_FAIL:
fallthrough; default: return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC;
}
}
staticbool ksz9x31_cable_test_failed(u16 status)
{ int stat = FIELD_GET(KSZ9x31_LMD_VCT_ST_MASK, status);
return stat == KSZ9x31_LMD_VCT_ST_FAIL;
}
staticbool ksz9x31_cable_test_fault_length_valid(u16 status)
{ switch (FIELD_GET(KSZ9x31_LMD_VCT_ST_MASK, status)) { case KSZ9x31_LMD_VCT_ST_OPEN:
fallthrough; case KSZ9x31_LMD_VCT_ST_SHORT: returntrue;
} returnfalse;
}
staticint ksz9x31_cable_test_one_pair(struct phy_device *phydev, int pair)
{ int ret, val;
/* KSZ9131RNX, DS00002841B-page 38, 4.14 LinkMD (R) Cable Diagnostic * To test each individual cable pair, set the cable pair in the Cable * Diagnostics Test Pair (VCT_PAIR[1:0]) field of the LinkMD Cable * Diagnostic Register, along with setting the Cable Diagnostics Test * Enable (VCT_EN) bit. The Cable Diagnostics Test Enable (VCT_EN) bit * will self clear when the test is concluded.
*/
ret = phy_write(phydev, KSZ9x31_LMD,
KSZ9x31_LMD_VCT_EN | KSZ9x31_LMD_VCT_PAIR(pair)); if (ret) return ret;
ret = ksz9x31_cable_test_wait_for_completion(phydev); if (ret) return ret;
val = phy_read(phydev, KSZ9x31_LMD); if (val < 0) return val;
if (ksz9x31_cable_test_failed(val)) return -EAGAIN;
ret = ethnl_cable_test_result(phydev,
ksz9x31_cable_test_get_pair(pair),
ksz9x31_cable_test_result_trans(val)); if (ret) return ret;
if (!ksz9x31_cable_test_fault_length_valid(val)) return 0;
if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
phydev->supported) ||
linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
phydev->supported))
pair_mask = 0xf; /* All pairs */ else
pair_mask = 0x3; /* Pairs A and B only */
/* Try harder if link partner is active */ while (pair_mask && retries--) {
for_each_set_bit(pair, &pair_mask, 4) {
ret = ksz9x31_cable_test_one_pair(phydev, pair); if (ret == -EAGAIN) continue; if (ret < 0) return ret;
clear_bit(pair, &pair_mask);
} /* If link partner is in autonegotiation mode it will send 2ms * of FLPs with at least 6ms of silence. * Add 2ms sleep to have better chances to hit this silence.
*/ if (pair_mask)
usleep_range(2000, 3000);
}
/* Report remaining unfinished pair result as unknown. */
for_each_set_bit(pair, &pair_mask, 4) {
ret = ethnl_cable_test_result(phydev,
ksz9x31_cable_test_get_pair(pair),
ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC);
}
*finished = true;
/* Restore cached bits from before LinkMD got started. */
rv = phy_modify(phydev, MII_CTRL1000,
CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER,
priv->vct_ctrl1000); if (rv) return rv;
switch (ctrl) { case ETH_TP_MDI:
val = KSZ886X_BMCR_DISABLE_AUTO_MDIX; break; case ETH_TP_MDI_X: /* Note: The naming of the bit KSZ886X_BMCR_FORCE_MDI is bit * counter intuitive, the "-X" in "1 = Force MDI" in the data * sheet seems to be missing: * 1 = Force MDI (sic!) (transmit on RX+/RX- pins) * 0 = Normal operation (transmit on TX+/TX- pins)
*/
val = KSZ886X_BMCR_DISABLE_AUTO_MDIX | KSZ886X_BMCR_FORCE_MDI; break; case ETH_TP_MDI_AUTO:
val = 0; break; default: return 0;
}
staticint ksz886x_config_aneg(struct phy_device *phydev)
{ int ret;
ret = genphy_config_aneg(phydev); if (ret) return ret;
if (phydev->autoneg != AUTONEG_ENABLE) { /* When autonegotation is disabled, we need to manually force * the link state. If we don't do this, the PHY will keep * sending Fast Link Pulses (FLPs) which are part of the * autonegotiation process. This is not desired when * autonegotiation is off.
*/
ret = phy_set_bits(phydev, MII_KSZPHY_CTRL,
KSZ886X_CTRL_FORCE_LINK); if (ret) return ret;
} else { /* If we had previously forced the link state, we need to * clear KSZ886X_CTRL_FORCE_LINK bit now. Otherwise, the PHY * will not perform autonegotiation.
*/
ret = phy_clear_bits(phydev, MII_KSZPHY_CTRL,
KSZ886X_CTRL_FORCE_LINK); if (ret) return ret;
}
/* The MDI-X configuration is automatically changed by the PHY after * switching from autoneg off to on. So, take MDI-X configuration under * own control and set it after autoneg configuration was done.
*/ return ksz886x_config_mdix(phydev, phydev->mdix_ctrl);
}
staticint ksz886x_mdix_update(struct phy_device *phydev)
{ int ret;
ret = phy_read(phydev, MII_BMCR); if (ret < 0) return ret;
staticint ksz9477_phy_errata(struct phy_device *phydev)
{ int err; int i;
/* Apply PHY settings to address errata listed in * KSZ9477, KSZ9897, KSZ9896, KSZ9567, KSZ8565 * Silicon Errata and Data Sheet Clarification documents. * * Document notes: Before configuring the PHY MMD registers, it is * necessary to set the PHY to 100 Mbps speed with auto-negotiation * disabled by writing to register 0xN100-0xN101. After writing the * MMD registers, and after all errata workarounds that involve PHY * register settings, write register 0xN100-0xN101 again to enable * and restart auto-negotiation.
*/
err = phy_write(phydev, MII_BMCR, BMCR_SPEED100 | BMCR_FULLDPLX); if (err) return err;
for (i = 0; i < ARRAY_SIZE(ksz9477_errata_writes); ++i) { conststruct ksz9477_errata_write *errata = &ksz9477_errata_writes[i];
for (i = 0; i < ARRAY_SIZE(kszphy_hw_stats); i++)
data[i] = kszphy_get_stat(phydev, i);
}
/* KSZ9477 PHY RXER Counter. Probably supported by other PHYs like KSZ9313, * etc. The counter is incremented when the PHY receives a frame with one or * more symbol errors. The counter is cleared when the register is read.
*/ #define MII_KSZ9477_PHY_RXER_COUNTER 0x15
/* Base register for Signal Quality Indicator (SQI) - Channel A * * MMD Address: MDIO_MMD_PMAPMD (0x01) * Register: 0xAC (Channel A) * Each channel (pair) has its own register: * Channel A: 0xAC * Channel B: 0xAD * Channel C: 0xAE * Channel D: 0xAF
*/ #define KSZ9477_MMD_SIGNAL_QUALITY_CHAN_A 0xac
/* SQI field mask for bits [14:8] * * SQI indicates relative quality of the signal. * A lower value indicates better signal quality.
*/ #define KSZ9477_MMD_SQI_MASK GENMASK(14, 8)
/* Number of SQI samples to average for a stable result. * * Reference: KSZ9477S Datasheet DS00002392C, Section 4.1.11 (page 26) * For noisy environments, a minimum of 30–50 readings is recommended.
*/ #define KSZ9477_SQI_SAMPLE_COUNT 40
/* The hardware SQI register provides a raw value from 0-127, where a lower * value indicates better signal quality. However, empirical testing has * shown that only the 0-7 range is relevant for a functional link. A raw * value of 8 or higher was measured directly before link drop. This aligns * with the OPEN Alliance recommendation that SQI=0 should represent the * pre-failure state. * * This table provides a non-linear mapping from the useful raw hardware * values (0-7) to the standard 0-7 SQI scale, where higher is better.
*/ staticconst u8 ksz_sqi_mapping[] = {
7, /* raw 0 -> SQI 7 */
7, /* raw 1 -> SQI 7 */
6, /* raw 2 -> SQI 6 */
5, /* raw 3 -> SQI 5 */
4, /* raw 4 -> SQI 4 */
3, /* raw 5 -> SQI 3 */
2, /* raw 6 -> SQI 2 */
1, /* raw 7 -> SQI 1 */
};
/** * kszphy_get_sqi - Read, average, and map Signal Quality Index (SQI) * @phydev: the PHY device * * This function reads and processes the raw Signal Quality Index from the * PHY. Based on empirical testing, a raw value of 8 or higher indicates a * pre-failure state and is mapped to SQI 0. Raw values from 0-7 are * mapped to the standard 0-7 SQI scale via a lookup table. * * Return: SQI value (0–7), or a negative errno on failure.
*/ staticint kszphy_get_sqi(struct phy_device *phydev)
{ int sum[KSZ9477_MAX_CHANNELS] = { 0 }; int worst_sqi = KSZ9477_SQI_MAX; int i, val, raw_sqi, ch;
u8 channels;
/* Determine applicable channels based on link speed */ if (phydev->speed == SPEED_1000)
channels = 4; elseif (phydev->speed == SPEED_100)
channels = 1; else return -EOPNOTSUPP;
/* Sample and accumulate SQI readings for each pair (currently only one). * * Reference: KSZ9477S Datasheet DS00002392C, Section 4.1.11 (page 26) * - The SQI register is updated every 2 µs. * - Values may fluctuate significantly, even in low-noise environments. * - For reliable estimation, average a minimum of 30–50 samples * (recommended for noisy environments) * - In noisy environments, individual readings are highly unreliable. * * We use 40 samples per pair with a delay of 3 µs between each * read to ensure new values are captured (2 µs update interval).
*/ for (i = 0; i < KSZ9477_SQI_SAMPLE_COUNT; i++) { for (ch = 0; ch < channels; ch++) {
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
KSZ9477_MMD_SIGNAL_QUALITY_CHAN_A + ch); if (val < 0) return val;
/* We communicate with the PHY via MDIO via SPI or * I2C, which is relatively slow. At least slower than * the update interval of the SQI register. * So, we can skip the delay between reads.
*/
}
}
/* Calculate average for each channel and find the worst SQI */ for (ch = 0; ch < channels; ch++) { int avg_raw_sqi = sum[ch] / KSZ9477_SQI_SAMPLE_COUNT; int mapped_sqi;
/* Handle the pre-fail/failed state first. */ if (avg_raw_sqi >= ARRAY_SIZE(ksz_sqi_mapping))
mapped_sqi = 0; else /* Use the lookup table for the good signal range. */
mapped_sqi = ksz_sqi_mapping[avg_raw_sqi];
if (mapped_sqi < worst_sqi)
worst_sqi = mapped_sqi;
}
staticint kszphy_resume(struct phy_device *phydev)
{ int ret;
ret = kszphy_generic_resume(phydev); if (ret) return ret;
/* After switching from power-down to normal mode, an internal global * reset is automatically generated. Wait a minimum of 1 ms before * read/write access to the PHY registers.
*/
usleep_range(1000, 2000);
ret = kszphy_config_reset(phydev); if (ret) return ret;
/* Enable PHY Interrupts */ if (phy_interrupt_is_valid(phydev)) {
phydev->interrupts = PHY_INTERRUPT_ENABLED; if (phydev->drv->config_intr)
phydev->drv->config_intr(phydev);
}
return 0;
}
/* Because of errata DS80000700A, receiver error following software * power down. Suspend and resume callbacks only disable and enable * external rmii reference clock.
*/ staticint ksz8041_resume(struct phy_device *phydev)
{
kszphy_enable_clk(phydev);
staticint ksz9477_resume(struct phy_device *phydev)
{ int ret;
/* No need to initialize registers if not powered down. */
ret = phy_read(phydev, MII_BMCR); if (ret < 0) return ret; if (!(ret & BMCR_PDOWN)) return 0;
genphy_resume(phydev);
/* After switching from power-down to normal mode, an internal global * reset is automatically generated. Wait a minimum of 1 ms before * read/write access to the PHY registers.
*/
usleep_range(1000, 2000);
/* Only KSZ9897 family of switches needs this fix. */ if ((phydev->phy_id & 0xf) == 1) {
ret = ksz9477_phy_errata(phydev); if (ret) return ret;
}
/* Enable PHY Interrupts */ if (phy_interrupt_is_valid(phydev)) {
phydev->interrupts = PHY_INTERRUPT_ENABLED; if (phydev->drv->config_intr)
phydev->drv->config_intr(phydev);
}
return 0;
}
staticint ksz8061_resume(struct phy_device *phydev)
{ int ret;
/* This function can be called twice when the Ethernet device is on. */
ret = phy_read(phydev, MII_BMCR); if (ret < 0) return ret; if (!(ret & BMCR_PDOWN)) return 0;
ret = kszphy_generic_resume(phydev); if (ret) return ret;
usleep_range(1000, 2000);
/* Re-program the value after chip is reset. */
ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_DEVID1, 0xB61A); if (ret) return ret;
/* Enable PHY Interrupts */ if (phy_interrupt_is_valid(phydev)) {
phydev->interrupts = PHY_INTERRUPT_ENABLED; if (phydev->drv->config_intr)
phydev->drv->config_intr(phydev);
}
priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM;
phydev->priv = priv;
priv->type = type;
kszphy_parse_led_mode(phydev);
clk = devm_clk_get_optional_enabled(&phydev->mdio.dev, "rmii-ref"); /* NOTE: clk may be NULL if building without CONFIG_HAVE_CLK */ if (!IS_ERR_OR_NULL(clk)) { unsignedlong rate = clk_get_rate(clk); bool rmii_ref_clk_sel_25_mhz;
if (type)
priv->rmii_ref_clk_sel = type->has_rmii_ref_clk_sel;
rmii_ref_clk_sel_25_mhz = of_property_read_bool(np,
--> --------------------
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.