aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/igb/e1000_phy.c
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2009-10-05 02:32:27 -0400
committerDavid S. Miller <davem@davemloft.net>2009-10-06 17:59:18 -0400
commitbf6f7a928d313ddecb0a16ea60fa6b45ac1414a7 (patch)
treee26e506f81bb02deab334b600930dd86b337fabc /drivers/net/igb/e1000_phy.c
parent008c3422d48b217792789bdea822dbc2efe2165c (diff)
igb: add locking to reads of the i2c interface
The current implementation of sgmii support isn't correctly locking the interfaces for reads/writes. This change pulls the read/write functionality out of 82575.c and moves it to phy.c. In addition it replaces the implementation in 82575.c with one that uses locking around the relocated i2c interface calls. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/igb/e1000_phy.c')
-rw-r--r--drivers/net/igb/e1000_phy.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c
index ee460600e74b..d4c928ccb294 100644
--- a/drivers/net/igb/e1000_phy.c
+++ b/drivers/net/igb/e1000_phy.c
@@ -239,6 +239,103 @@ out:
239} 239}
240 240
241/** 241/**
242 * igb_read_phy_reg_i2c - Read PHY register using i2c
243 * @hw: pointer to the HW structure
244 * @offset: register offset to be read
245 * @data: pointer to the read data
246 *
247 * Reads the PHY register at offset using the i2c interface and stores the
248 * retrieved information in data.
249 **/
250s32 igb_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data)
251{
252 struct e1000_phy_info *phy = &hw->phy;
253 u32 i, i2ccmd = 0;
254
255
256 /*
257 * Set up Op-code, Phy Address, and register address in the I2CCMD
258 * register. The MAC will take care of interfacing with the
259 * PHY to retrieve the desired data.
260 */
261 i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
262 (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) |
263 (E1000_I2CCMD_OPCODE_READ));
264
265 wr32(E1000_I2CCMD, i2ccmd);
266
267 /* Poll the ready bit to see if the I2C read completed */
268 for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
269 udelay(50);
270 i2ccmd = rd32(E1000_I2CCMD);
271 if (i2ccmd & E1000_I2CCMD_READY)
272 break;
273 }
274 if (!(i2ccmd & E1000_I2CCMD_READY)) {
275 hw_dbg("I2CCMD Read did not complete\n");
276 return -E1000_ERR_PHY;
277 }
278 if (i2ccmd & E1000_I2CCMD_ERROR) {
279 hw_dbg("I2CCMD Error bit set\n");
280 return -E1000_ERR_PHY;
281 }
282
283 /* Need to byte-swap the 16-bit value. */
284 *data = ((i2ccmd >> 8) & 0x00FF) | ((i2ccmd << 8) & 0xFF00);
285
286 return 0;
287}
288
289/**
290 * igb_write_phy_reg_i2c - Write PHY register using i2c
291 * @hw: pointer to the HW structure
292 * @offset: register offset to write to
293 * @data: data to write at register offset
294 *
295 * Writes the data to PHY register at the offset using the i2c interface.
296 **/
297s32 igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data)
298{
299 struct e1000_phy_info *phy = &hw->phy;
300 u32 i, i2ccmd = 0;
301 u16 phy_data_swapped;
302
303
304 /* Swap the data bytes for the I2C interface */
305 phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00);
306
307 /*
308 * Set up Op-code, Phy Address, and register address in the I2CCMD
309 * register. The MAC will take care of interfacing with the
310 * PHY to retrieve the desired data.
311 */
312 i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
313 (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) |
314 E1000_I2CCMD_OPCODE_WRITE |
315 phy_data_swapped);
316
317 wr32(E1000_I2CCMD, i2ccmd);
318
319 /* Poll the ready bit to see if the I2C read completed */
320 for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
321 udelay(50);
322 i2ccmd = rd32(E1000_I2CCMD);
323 if (i2ccmd & E1000_I2CCMD_READY)
324 break;
325 }
326 if (!(i2ccmd & E1000_I2CCMD_READY)) {
327 hw_dbg("I2CCMD Write did not complete\n");
328 return -E1000_ERR_PHY;
329 }
330 if (i2ccmd & E1000_I2CCMD_ERROR) {
331 hw_dbg("I2CCMD Error bit set\n");
332 return -E1000_ERR_PHY;
333 }
334
335 return 0;
336}
337
338/**
242 * igb_read_phy_reg_igp - Read igp PHY register 339 * igb_read_phy_reg_igp - Read igp PHY register
243 * @hw: pointer to the HW structure 340 * @hw: pointer to the HW structure
244 * @offset: register offset to be read 341 * @offset: register offset to be read