phyi2c.c (3430B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: phyi2c.c 8 * Purpose: I2C bus read/write routines for SFP copper PHY devices 9 */ 10 11 #if defined(BCM_ESW_SUPPORT) && defined(INCLUDE_I2C) 12 #include <sal/types.h> 13 #include <soc/drv.h> 14 #include <soc/phy.h> 15 #include <soc/i2c.h> 16 #include <soc/debug.h> 17 18 #ifndef BCMSWAP16 19 #define BCMSWAP16(val) \ 20 ((uint16)( \ 21 (((uint16)(val) & (uint16)0x00ffU) << 8) | \ 22 (((uint16)(val) & (uint16)0xff00U) >> 8) )) 23 #endif 24 25 /* customer specific phy bus read/write hook pointers */ 26 typedef struct { 27 soc_phy_bus_rd_t rd; 28 soc_phy_bus_wr_t wr; 29 } soc_phy_bus_hook_t; 30 31 STATIC soc_phy_bus_hook_t _soc_phy_bus_hook[SOC_MAX_NUM_DEVICES]; 32 33 34 /* 35 * Function: 36 * phy_i2c_miireg_read 37 * Purpose: 38 * Read a MII register of the given PHY device on the I2C bus. Typically it is 39 * a copper SFP PHY device. 40 * Parameters: 41 * unit - StrataSwitch unit #. 42 * phy_id - the address on the I2C bus. 43 * phy_reg_addr - MII register address. 44 * phy_rd_data - pointer to a 16bit storage to hold read data. 45 * Returns: 46 * SOC_E_XXX 47 */ 48 49 int 50 phy_i2c_miireg_read (int unit,uint32 phy_id,uint32 phy_reg_addr, 51 uint16 *phy_rd_data) 52 { 53 int rv = SOC_E_NONE; 54 55 if (_soc_phy_bus_hook[unit].rd) { 56 return (*_soc_phy_bus_hook[unit].rd)(unit,phy_id,phy_reg_addr,phy_rd_data); 57 } 58 59 /* Make sure that we're already attached, or go get attached */ 60 if (!soc_i2c_is_attached(unit)) { 61 if ((rv = soc_i2c_attach(unit, 0, 0)) <= 0) { 62 return rv; 63 } 64 } 65 rv = soc_i2c_read_word_data(unit,phy_id,phy_reg_addr,phy_rd_data); 66 67 if (rv == SOC_E_NONE) { 68 *phy_rd_data = BCMSWAP16(*phy_rd_data); 69 } 70 return rv; 71 } 72 73 /* 74 * Function: 75 * phy_i2c_miireg_write 76 * Purpose: 77 * Write to a MII register of the given PHY device on the I2C bus. Typically it is 78 * a copper SFP PHY device. 79 * Parameters: 80 * unit - StrataSwitch unit #. 81 * phy_id - the address on the I2C bus. 82 * phy_reg_addr - MII register address. 83 * phy_wr_data - 16bit value to write to the MII register. 84 * Returns: 85 * SOC_E_XXX 86 */ 87 88 int 89 phy_i2c_miireg_write (int unit,uint32 phy_id,uint32 phy_reg_addr, 90 uint16 phy_wr_data) 91 { 92 int rv = SOC_E_NONE; 93 94 if (_soc_phy_bus_hook[unit].wr) { 95 return (*_soc_phy_bus_hook[unit].wr)(unit,phy_id,phy_reg_addr,phy_wr_data); 96 } 97 98 /* Make sure that we're already attached, or go get attached */ 99 if (!soc_i2c_is_attached(unit)) { 100 if ((rv = soc_i2c_attach(unit, 0, 0)) <= 0) { 101 return rv; 102 } 103 } 104 105 rv = soc_i2c_write_word_data(unit,phy_id,phy_reg_addr,BCMSWAP16(phy_wr_data)); 106 return rv; 107 } 108 109 /* 110 * Function: 111 * phy_i2c_bus_func_hook_set 112 * Purpose: 113 * Install customer specific I2C bus read/write routines 114 * 115 * Parameters: 116 * unit - StrataSwitch unit #. 117 * rd - I2C bus read routine. 118 * wr - I2C bus write routine. 119 * Returns: 120 * SOC_E_XXX 121 */ 122 123 int phy_i2c_bus_func_hook_set (int unit, soc_phy_bus_rd_t rd, soc_phy_bus_wr_t wr) 124 { 125 _soc_phy_bus_hook[unit].rd = rd; 126 _soc_phy_bus_hook[unit].wr = wr; 127 return SOC_E_NONE; 128 } 129 #else 130 int _soc_phy_phyi2c_not_empty; 131 #endif