Lines Matching +full:i2c +full:- +full:protocol

1 // SPDX-License-Identifier: GPL-2.0
3 * MDIO I2C bridge
5 * Copyright (C) 2015-2016 Russell King
8 * Network PHYs can appear on I2C buses when they are part of SFP module.
13 #include <linux/i2c.h>
14 #include <linux/mdio/mdio-i2c.h>
19 * I2C bus addresses 0x50 and 0x51 are normally an EEPROM, which is
36 struct i2c_adapter *i2c = bus->priv; in i2c_mii_read_default_c45() local
54 msgs[0].len = p - addr; in i2c_mii_read_default_c45()
61 ret = i2c_transfer(i2c, msgs, ARRAY_SIZE(msgs)); in i2c_mii_read_default_c45()
71 struct i2c_adapter *i2c = bus->priv; in i2c_mii_write_default_c45() local
90 msg.len = p - data; in i2c_mii_write_default_c45()
93 ret = i2c_transfer(i2c, &msg, 1); in i2c_mii_write_default_c45()
100 return i2c_mii_read_default_c45(bus, phy_id, -1, reg); in i2c_mii_read_default_c22()
106 return i2c_mii_write_default_c45(bus, phy_id, -1, reg, val); in i2c_mii_write_default_c22()
112 struct i2c_adapter *i2c = bus->priv; in smbus_byte_mii_read_default_c22() local
119 i2c_lock_bus(i2c, I2C_LOCK_SEGMENT); in smbus_byte_mii_read_default_c22()
121 ret = __i2c_smbus_xfer(i2c, i2c_mii_phy_addr(phy_id), 0, in smbus_byte_mii_read_default_c22()
129 ret = __i2c_smbus_xfer(i2c, i2c_mii_phy_addr(phy_id), 0, in smbus_byte_mii_read_default_c22()
134 i2c_unlock_bus(i2c, I2C_LOCK_SEGMENT); in smbus_byte_mii_read_default_c22()
147 struct i2c_adapter *i2c = bus->priv; in smbus_byte_mii_write_default_c22() local
156 i2c_lock_bus(i2c, I2C_LOCK_SEGMENT); in smbus_byte_mii_write_default_c22()
158 ret = __i2c_smbus_xfer(i2c, i2c_mii_phy_addr(phy_id), 0, in smbus_byte_mii_write_default_c22()
166 ret = __i2c_smbus_xfer(i2c, i2c_mii_phy_addr(phy_id), 0, in smbus_byte_mii_write_default_c22()
171 i2c_unlock_bus(i2c, I2C_LOCK_SEGMENT); in smbus_byte_mii_write_default_c22()
176 /* RollBall SFPs do not access internal PHY via I2C address 0x56, but
181 * ------- ---- -------- -----------
200 static int __i2c_transfer_err(struct i2c_adapter *i2c, struct i2c_msg *msgs, in __i2c_transfer_err() argument
205 ret = __i2c_transfer(i2c, msgs, num); in __i2c_transfer_err()
209 return -EIO; in __i2c_transfer_err()
214 static int __i2c_rollball_get_page(struct i2c_adapter *i2c, int bus_addr, in __i2c_rollball_get_page() argument
230 return __i2c_transfer_err(i2c, msgs, 2); in __i2c_rollball_get_page()
233 static int __i2c_rollball_set_page(struct i2c_adapter *i2c, int bus_addr, in __i2c_rollball_set_page() argument
247 return __i2c_transfer_err(i2c, &msg, 1); in __i2c_rollball_set_page()
260 * unfortunately tests show that this does not work :-( Changed SFP_PAGE does
263 static int i2c_transfer_rollball(struct i2c_adapter *i2c, in i2c_transfer_rollball() argument
269 i2c_lock_bus(i2c, I2C_LOCK_SEGMENT); in i2c_transfer_rollball()
272 ret = __i2c_rollball_get_page(i2c, msgs->addr, &saved_page); in i2c_transfer_rollball()
277 ret = __i2c_rollball_set_page(i2c, msgs->addr, SFP_PAGE_ROLLBALL_MDIO); in i2c_transfer_rollball()
282 ret = __i2c_transfer_err(i2c, msgs, num); in i2c_transfer_rollball()
287 ret = __i2c_rollball_set_page(i2c, msgs->addr, saved_page); in i2c_transfer_rollball()
290 i2c_unlock_bus(i2c, I2C_LOCK_SEGMENT); in i2c_transfer_rollball()
298 struct i2c_adapter *i2c = bus->priv; in i2c_rollball_mii_poll() local
325 ret = i2c_transfer_rollball(i2c, msgs, ARRAY_SIZE(msgs)); in i2c_rollball_mii_poll()
331 } while (i-- > 0); in i2c_rollball_mii_poll()
333 dev_dbg(&bus->dev, "poll timed out\n"); in i2c_rollball_mii_poll()
335 return -ETIMEDOUT; in i2c_rollball_mii_poll()
341 struct i2c_adapter *i2c = bus->priv; in i2c_rollball_mii_cmd() local
358 return i2c_transfer_rollball(i2c, msgs, ARRAY_SIZE(msgs)); in i2c_rollball_mii_cmd()
383 if (ret == -ETIMEDOUT) in i2c_mii_read_rollball()
422 static int i2c_mii_init_rollball(struct i2c_adapter *i2c) in i2c_mii_init_rollball() argument
439 ret = i2c_transfer(i2c, &msg, 1); in i2c_mii_init_rollball()
443 return -EIO; in i2c_mii_init_rollball()
448 static bool mdio_i2c_check_functionality(struct i2c_adapter *i2c, in mdio_i2c_check_functionality() argument
449 enum mdio_i2c_proto protocol) in mdio_i2c_check_functionality() argument
451 if (i2c_check_functionality(i2c, I2C_FUNC_I2C)) in mdio_i2c_check_functionality()
454 if (i2c_check_functionality(i2c, I2C_FUNC_SMBUS_BYTE_DATA) && in mdio_i2c_check_functionality()
455 protocol == MDIO_I2C_MARVELL_C22) in mdio_i2c_check_functionality()
461 struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c, in mdio_i2c_alloc() argument
462 enum mdio_i2c_proto protocol) in mdio_i2c_alloc() argument
467 if (!mdio_i2c_check_functionality(i2c, protocol)) in mdio_i2c_alloc()
468 return ERR_PTR(-EINVAL); in mdio_i2c_alloc()
472 return ERR_PTR(-ENOMEM); in mdio_i2c_alloc()
474 snprintf(mii->id, MII_BUS_ID_SIZE, "i2c:%s", dev_name(parent)); in mdio_i2c_alloc()
475 mii->parent = parent; in mdio_i2c_alloc()
476 mii->priv = i2c; in mdio_i2c_alloc()
479 if (i2c_check_functionality(i2c, I2C_FUNC_SMBUS_BYTE_DATA) && in mdio_i2c_alloc()
480 !i2c_check_functionality(i2c, I2C_FUNC_I2C)) { in mdio_i2c_alloc()
481 mii->read = smbus_byte_mii_read_default_c22; in mdio_i2c_alloc()
482 mii->write = smbus_byte_mii_write_default_c22; in mdio_i2c_alloc()
486 switch (protocol) { in mdio_i2c_alloc()
488 ret = i2c_mii_init_rollball(i2c); in mdio_i2c_alloc()
491 "Cannot initialize RollBall MDIO I2C protocol: %d\n", in mdio_i2c_alloc()
497 mii->read_c45 = i2c_mii_read_rollball; in mdio_i2c_alloc()
498 mii->write_c45 = i2c_mii_write_rollball; in mdio_i2c_alloc()
501 mii->read = i2c_mii_read_default_c22; in mdio_i2c_alloc()
502 mii->write = i2c_mii_write_default_c22; in mdio_i2c_alloc()
503 mii->read_c45 = i2c_mii_read_default_c45; in mdio_i2c_alloc()
504 mii->write_c45 = i2c_mii_write_default_c45; in mdio_i2c_alloc()
513 MODULE_DESCRIPTION("MDIO I2C bridge library");