cpu.c (9957B)
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 * I2C access from the CPU 8 */ 9 10 #include <sal/types.h> 11 #include <shared/bsl.h> 12 #include <soc/drv.h> 13 #include <soc/i2c.h> 14 15 #if defined(__DUNE_GTO_BCM_CPU__) || defined(__DUNE_WRX_BCM_CPU__) || defined(__DUNE_SLK_BCM_CPU__) || defined(INCLUDE_CPU_I2C) 16 17 #include <sal/appl/i2c.h> 18 19 20 #define CPU_I2C_MAX_ADDRESS_SIZE 4 /* Maximum number of bytes of an address in an I2C device (register address) */ 21 22 uint8 cpu_i2c_bus_num_default = CPU_I2C_BUS_NUM_DEFAULT; 23 24 int cpu_i2c_write(int chip, int addr, CPU_I2C_BUS_LEN alen, int val) 25 { 26 int ret, bus_num = CPU_I2C_BUS_NUM_DEFAULT; 27 uint32 value; 28 uint8 data_len = alen & 0xf, addr_len = (alen >> 4) & 0xf, i, data[CPU_I2C_MAX_ADDRESS_SIZE] = {0}; 29 30 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META( 31 "cpu_i2c_write: bus:%d dev:@%02x reg:%0x data:%x\n"), bus_num, chip, addr, val)); 32 33 switch (alen) 34 { 35 /* No internal/register address */ 36 case CPU_I2C_ALEN_NONE_DLEN_BYTE: 37 case CPU_I2C_ALEN_NONE_DLEN_WORD: 38 case CPU_I2C_ALEN_NONE_DLEN_LONG: 39 case CPU_I2C_ALEN_BYTE_DLEN_BYTE: /* address is 1 byte long */ 40 case CPU_I2C_ALEN_WORD_DLEN_WORD: /* address is word (2 bytes) long */ 41 case CPU_I2C_ALEN_BYTE_DLEN_LONG: /* address is 1 bytes long, data is 4 byte long*/ 42 case CPU_I2C_ALEN_WORD_DLEN_LONG: /* address is 1 bytes long, data is 4 byte long*/ 43 case CPU_I2C_ALEN_LONG_DLEN_LONG: /* address is 4 bytes long */ 44 case CPU_I2C_ALEN_BYTE_DLEN_WORD: /* address is 1 bytes long, data is 2 bytes long */ 45 break; 46 default: 47 LOG_ERROR(BSL_LS_SOC_I2C, (BSL_META( 48 "error - unsupported address and data length given = 0x%x"), (unsigned)alen)); 49 return SOC_E_PARAM; 50 } 51 52 /* build data as big endian */ 53 value = val; 54 for (i = data_len ; i > 0 ;) { 55 data[--i] = value & 0xff; 56 value >>= 8; 57 } 58 59 /* Perform an I2C write operation */ 60 ret = sal_i2c_write(CPU_I2C_BUS_NUM_DEFAULT, chip, (uint32)addr, addr_len, data, data_len); 61 62 if (ret != SOC_E_NONE) 63 { 64 LOG_ERROR(BSL_LS_SOC_I2C, (BSL_META( 65 "Error in %s: cpu_i2c_write() returned with error.\n"), FUNCTION_NAME())); 66 } 67 68 return ret; 69 } 70 71 /* perform an I2C read operation by the CPU card */ 72 int cpu_i2c_read_extended(int chip, int addr, CPU_I2C_BUS_LEN alen, int* p_val, int donot_print_errors) 73 { 74 int ret = 0; 75 int bus_num = CPU_I2C_BUS_NUM_DEFAULT; 76 uint32 value; 77 uint8 data_len = alen & 0xf, addr_len = (alen >> 4) & 0xf, i, result[CPU_I2C_MAX_ADDRESS_SIZE] = {0}; 78 79 LOG_VERBOSE(BSL_LS_SOC_I2C, (BSL_META( 80 "cpu_i2c_read: bus:%d dev:@%02x reg:%0x\n"), bus_num, chip, addr)); 81 82 switch (alen) 83 { 84 /* No internal/register address */ 85 case CPU_I2C_ALEN_NONE_DLEN_BYTE: 86 case CPU_I2C_ALEN_NONE_DLEN_WORD: 87 case CPU_I2C_ALEN_NONE_DLEN_LONG: 88 89 case CPU_I2C_ALEN_BYTE_DLEN_BYTE: /* address is 1 byte long */ 90 case CPU_I2C_ALEN_WORD_DLEN_WORD: /* address is word (2 bytes) long */ 91 case CPU_I2C_ALEN_BYTE_DLEN_LONG: /* address is 1 bytes long, data is 4 byte long*/ 92 case CPU_I2C_ALEN_WORD_DLEN_LONG: /* address is 1 bytes long, data is 4 byte long*/ 93 case CPU_I2C_ALEN_LONG_DLEN_LONG: /* address is 4 bytes long */ 94 case CPU_I2C_ALEN_BYTE_DLEN_WORD: /* address is 1 bytes long, data is 2 bytes long */ 95 break; 96 default: 97 LOG_ERROR(BSL_LS_SOC_I2C, (BSL_META( 98 "error - unsupported address and data length given = 0x%x"), (unsigned)alen)); 99 return SOC_E_PARAM; 100 } /* switch*/ 101 102 /* Perform an I2C read operation */ 103 ret = sal_i2c_read(CPU_I2C_BUS_NUM_DEFAULT, chip, (uint32)addr, addr_len, result, data_len); 104 105 /* build results value according received as big endian */ 106 value = 0; 107 if (ret == SOC_E_NONE) { 108 for (i = 0 ; i < data_len; ++i) { 109 value = (value << 8) | result[i]; 110 } 111 LOG_INFO(BSL_LS_SOC_I2C, (BSL_META( 112 "cpu_i2c_read: bus:%d dev:@%02x reg:%0x data:%x\n"), bus_num, chip, addr, value)); 113 } else if (!donot_print_errors) { 114 LOG_ERROR(BSL_LS_SOC_I2C, (BSL_META("cpu_i2c_read() returned with error.\n"))); 115 } 116 *p_val = value; 117 return ret; 118 } 119 120 int cpu_i2c_read(int chip, int addr, CPU_I2C_BUS_LEN alen, int* p_val) 121 { 122 return cpu_i2c_read_extended(chip, addr, alen, p_val, 0); 123 } 124 125 /* perform an I2C read operation on an I2C device connected to the CPU */ 126 soc_error_t cpu_i2c_read_generic( 127 uint8 i2c_bus, /* The number of the I2C bus to access on */ 128 uint16 i2c_dev,/* the device on the I2C bus (slave address) to be accessed */ 129 uint8 alen, /* the length of the address in bytes, should be between 0 and 4. */ 130 uint8 dlen, /* the length of the data to read. */ 131 uint32 addr, /* The address in the device to be accessed (register address). Used if alen>0 */ 132 uint8 *data) /* the buffer for the data to be read. */ 133 { 134 return sal_i2c_read(i2c_bus, i2c_dev, addr, alen, data, dlen); 135 } 136 137 /* perform an I2C write operation on an I2C device connected to the CPU */ 138 soc_error_t cpu_i2c_write_generic( 139 uint8 i2c_bus, /* The number of the I2C bus to access on */ 140 uint16 i2c_dev,/* the device on the I2C bus (slave address) to be accessed */ 141 uint8 alen, /* the length of the address in bytes, should be between 0 and 4. */ 142 uint8 dlen, /* the length of the data to read. */ 143 uint32 addr, /* The address in the device to be accessed (register address). Used if alen>0 */ 144 uint8 *data) /* the buffer for the data to be read. */ 145 { 146 return sal_i2c_write(i2c_bus, i2c_dev, addr, alen, data, dlen); 147 } 148 149 150 151 /* 152 * Function: cpu_i2c_device_present 153 * Purpose: Probe the I2C bus using saddr, report if a device responds. 154 * The I2C bus is released upon return. 155 * No further action is taken. 156 * 157 * Parameters: 158 * saddr - I2C slave address 159 * 160 * Return: 161 * SOC_E_NONE - An I2C device responds at the indicated saddr. 162 * otherwise - No I2C response at the indicated saddr, or I/O error. 163 */ 164 int 165 cpu_i2c_device_present(int bus, i2c_saddr_t saddr) { 166 return sal_i2c_device_present(bus, saddr); 167 } 168 169 /* 170 * Function: cpu_i2c_block_read 171 * Purpose: Read a block of data from I2c device 172 * 173 * Parameters: 174 * bus - cpu controller to use 175 * saddr - slave address 176 * addr - interal starting address, only 8bit addressing as of now 177 * data - pointer to buffer 178 * len - len of data to be read 179 * Return: 180 * SOC_E_NONE - An I2C device responds at the indicated saddr. 181 * otherwise - No I2C response at the indicated saddr, or I/O error. 182 */ 183 int 184 cpu_i2c_block_read(int bus, i2c_saddr_t saddr, 185 uint8 reg, uint8 *data, uint8 *len) 186 { 187 188 int rv; 189 190 if (*len == 0) { 191 LOG_ERROR(BSL_LS_SOC_I2C, 192 (BSL_META("ERROR in cpu_i2c_block_read: invalid len specified (%d)"), 193 *len)); 194 return SOC_E_PARAM; 195 } 196 rv = sal_i2c_read(bus, saddr, reg, 1, data, *len); 197 198 if (rv != SOC_E_NONE) { 199 LOG_ERROR(BSL_LS_SOC_I2C, 200 (BSL_META("\nFailed reading %d bytes data from %x at device saddr %x"), 201 *len, reg, saddr)); 202 return rv; 203 } 204 return SOC_E_NONE; 205 } 206 207 /* 208 * Function: cpu_i2c_block_write 209 * Purpose: Write a block of data from I2c device 210 * 211 * Parameters: 212 * bus - cpu controller to use 213 * saddr - slave address 214 * addr - interal starting address, only 8bit addressing as of now 215 * data - pointer to buffer 216 * len - len of data to be read 217 * Return: 218 * SOC_E_NONE - An I2C device responds at the indicated saddr. 219 * otherwise - No I2C response at the indicated saddr, or I/O error. 220 */ 221 int 222 cpu_i2c_block_write(int bus, i2c_saddr_t saddr, 223 uint8 reg, uint8 *data, uint8 len) 224 { 225 int rv = sal_i2c_write_split(bus, saddr, reg, 1, data, len); 226 227 if (rv != SOC_E_NONE) { 228 LOG_ERROR(BSL_LS_SOC_I2C, 229 (BSL_META("\nFailed reading %d bytes data from %x at device saddr %x"), 230 len, reg, saddr)); 231 return rv; 232 } 233 return SOC_E_NONE; 234 } 235 236 237 /* Write to the internal device Address space using I2C */ 238 soc_error_t cpu_i2c_device_read( 239 uint8 i2c_bus, /* The number of the I2C bus to access on */ 240 uint8 i2c_dev, /* the device on the I2C bus (slave address) to be accessed */ 241 uint32 addr, /* The address to access in the internal device address space */ 242 uint32 *value) /* the value to be read. */ 243 { 244 unsigned i; 245 uint8 data[sizeof(*value)]; 246 247 soc_error_t ret = sal_i2c_read(i2c_bus, i2c_dev, addr, sizeof(addr), data, sizeof(*value)); 248 /* build value according received as big endian */ 249 *value = 0; 250 for (i = 0 ; i < sizeof(*value); ++i) { 251 *value = (*value << 8) | data[i]; 252 } 253 return ret; 254 } 255 256 /* Write to the internal device Address space using I2C */ 257 soc_error_t cpu_i2c_device_write( 258 uint8 i2c_bus, /* The number of the I2C bus to access on */ 259 uint8 i2c_dev, /* the device on the I2C bus (slave address) to be accessed */ 260 uint32 addr, /* The address to access in the internal device address space */ 261 uint32 value) /* the value to be written. */ 262 { 263 unsigned i; 264 uint8 data[sizeof(value)]; 265 266 /* copy the address to data as big endian */ 267 for (i = sizeof(value) ; i > 0 ; ) { 268 data[--i] = value & 0xff; 269 value >>= 8; 270 } 271 /* The device returns an error on writes, even though they are performed */ 272 sal_i2c_write(i2c_bus, i2c_dev, addr, sizeof(addr), data, sizeof(value)); 273 return SOC_E_NONE; /* ignore errors */ 274 } 275 276 277 #else 278 int _src_soc_i2c_cpu_c_not_empty; 279 #endif /* defined(__DUNE_GTO_BCM_CPU__) || defined(__DUNE_WRX_BCM_CPU__) || defined(__DUNE_SLK_BCM_CPU__) || defined(INCLUDE_CPU_I2C) */