staticint i2c_mii_read_default_c22(struct mii_bus *bus, int phy_id, int reg)
{ return i2c_mii_read_default_c45(bus, phy_id, -1, reg);
}
staticint i2c_mii_write_default_c22(struct mii_bus *bus, int phy_id, int reg,
u16 val)
{ return i2c_mii_write_default_c45(bus, phy_id, -1, reg, val);
}
staticint smbus_byte_mii_read_default_c22(struct mii_bus *bus, int phy_id, int reg)
{ struct i2c_adapter *i2c = bus->priv; union i2c_smbus_data smbus_data; int val = 0, ret;
if (!i2c_mii_valid_phy_id(phy_id)) return0;
i2c_lock_bus(i2c, I2C_LOCK_SEGMENT);
ret = __i2c_smbus_xfer(i2c, i2c_mii_phy_addr(phy_id), 0,
I2C_SMBUS_READ, reg,
I2C_SMBUS_BYTE_DATA, &smbus_data); if (ret < 0) goto unlock;
val = (smbus_data.byte & 0xff) << 8;
ret = __i2c_smbus_xfer(i2c, i2c_mii_phy_addr(phy_id), 0,
I2C_SMBUS_READ, reg,
I2C_SMBUS_BYTE_DATA, &smbus_data);
unlock:
i2c_unlock_bus(i2c, I2C_LOCK_SEGMENT);
if (ret < 0) return ret;
val |= smbus_data.byte & 0xff;
return val;
}
staticint smbus_byte_mii_write_default_c22(struct mii_bus *bus, int phy_id, int reg, u16 val)
{ struct i2c_adapter *i2c = bus->priv; union i2c_smbus_data smbus_data; int ret;
if (!i2c_mii_valid_phy_id(phy_id)) return0;
smbus_data.byte = (val & 0xff00) >> 8;
i2c_lock_bus(i2c, I2C_LOCK_SEGMENT);
ret = __i2c_smbus_xfer(i2c, i2c_mii_phy_addr(phy_id), 0,
I2C_SMBUS_WRITE, reg,
I2C_SMBUS_BYTE_DATA, &smbus_data); if (ret < 0) goto unlock;
smbus_data.byte = val & 0xff;
ret = __i2c_smbus_xfer(i2c, i2c_mii_phy_addr(phy_id), 0,
I2C_SMBUS_WRITE, reg,
I2C_SMBUS_BYTE_DATA, &smbus_data);
unlock:
i2c_unlock_bus(i2c, I2C_LOCK_SEGMENT);
return ret < 0 ? ret : 0;
}
/* RollBall SFPs do not access internal PHY via I2C address 0x56, but *insteadviaaddress0x51,whenSFPpageissetto0x03andpasswordto *0xffffffff. * *addresssizecontentsdescription *------------------------------ *0x801CMD0x01/0x02/0x04forwrite/read/done *0x811DEVClause45device *0x822REGClause45register *0x842VALRegistervalue
*/ #define ROLLBALL_PHY_I2C_ADDR 0x51
/* In order to not interfere with other SFP code (which possibly may manipulate *SFP_PAGE),foreverytransferwedothis: *1.lockthebus *2.savecontentofSFP_PAGE *3.setSFP_PAGEto3 *4.dothetransfer *5.restoreoriginalSFP_PAGE *6.unlockthebus *Notethatonemightthinkthatsteps2to5couldbetheoreticallydoneall *inonecalltoi2c_transfer(byconstructingmsgsarrayinsuchaway),but *unfortunatelytestsshowthatthisdoesnotwork:-(ChangedSFP_PAGEdoes *nottakeintoaccountuntili2c_transfer()isdone.
*/ staticint i2c_transfer_rollball(struct i2c_adapter *i2c, struct i2c_msg *msgs, int num)
{ int ret, main_err = 0;
u8 saved_page;
i2c_lock_bus(i2c, I2C_LOCK_SEGMENT);
/* save original page */
ret = __i2c_rollball_get_page(i2c, msgs->addr, &saved_page); if (ret) goto unlock;
/* change to RollBall MDIO page */
ret = __i2c_rollball_set_page(i2c, msgs->addr, SFP_PAGE_ROLLBALL_MDIO); if (ret) goto unlock;
/* do the transfer; we try to restore original page if this fails */
ret = __i2c_transfer_err(i2c, msgs, num); if (ret)
main_err = ret;
/* restore original page */
ret = __i2c_rollball_set_page(i2c, msgs->addr, saved_page);
unlock:
i2c_unlock_bus(i2c, I2C_LOCK_SEGMENT);
return main_err ? : ret;
}
staticint i2c_rollball_mii_poll(struct mii_bus *bus, int bus_addr, u8 *buf,
size_t len)
{ struct i2c_adapter *i2c = bus->priv; struct i2c_msg msgs[2];
u8 cmd_addr, tmp, *res; int i, ret;
/* Only use SMBus if we have no other choice */ if (i2c_check_functionality(i2c, I2C_FUNC_SMBUS_BYTE_DATA) &&
!i2c_check_functionality(i2c, I2C_FUNC_I2C)) {
mii->read = smbus_byte_mii_read_default_c22;
mii->write = smbus_byte_mii_write_default_c22; return mii;
}
switch (protocol) { case MDIO_I2C_ROLLBALL:
ret = i2c_mii_init_rollball(i2c); if (ret < 0) {
dev_err(parent, "Cannot initialize RollBall MDIO I2C protocol: %d\n",
ret);
mdiobus_free(mii); return ERR_PTR(ret);
}
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.