xfp.c (10515B)
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 * BCM56xx I2C Device Driver for XFP modules. 8 */ 9 #include <sal/types.h> 10 #include <soc/drv.h> 11 #include <soc/error.h> 12 #include <soc/debug.h> 13 #include <soc/i2c.h> 14 #include <shared/bsl.h> 15 #define XFP_PAGE_SIZE 1 /* Bytes per page */ 16 #define XFP_DEVICE_SIZE (256*XFP_PAGE_SIZE) /* 256 bytes */ 17 #define XFP_ACK_RETRY_COUNT 1000 /* Number of retry polls */ 18 19 /* 20 * Function: xfp_ack_poll 21 * 22 * Purpose: Poll the device to determine if it is ready for IO. 23 * When the chip writes data, it will become unresponsive 24 * for a period of Time Tw (Internal Write Delay). We could 25 * either wait the maximum amount of time for the device to 26 * finish it's write-cycle (10ms), or we can poll the device 27 * for a specified operation (r/w) until it responds with an 28 * ACK. This routine polls the device until it is responsive. 29 * 30 * Parameters: 31 * unit - StrataSwitch device number or I2C bus number 32 * bus_addr - chip IO (I2C) slave bus address byte(s) 33 * 34 * Returns: 35 * Number of Poll operations required to contact device, or 36 * XFP_ACK_RETRY_COUNT if the device is not online or responding. 37 * 38 * 39 * Notes: 40 * See also: soc_i2c_ack_poll 41 */ 42 STATIC INLINE int 43 xfp_ack_poll(int unit, i2c_bus_addr_t bus_addr) 44 { 45 return soc_i2c_ack_poll(unit, bus_addr, XFP_ACK_RETRY_COUNT); 46 } 47 48 /* 49 * Function: xfp_read 50 * 51 * Purpose: Read len bytes of data into buffer, update len with total 52 * amount read. 53 * 54 * Parameters: 55 * unit - StrataSwitch device number or I2C bus number 56 * devno - chip device id 57 * addr - XFP memory address to read from 58 * data - address of data buffer to read into 59 * len - address containing number of bytes read into data buffer (updated 60 * with number of bytes read on completion). 61 * 62 * Returns: data bufffer filled in with data from address, number of 63 * bytes read is updated in len field. Status code: 64 * 65 * SOC_E_NONE -- no error encounter 66 * SOC_E_TIMEOUT - chip timeout or data error 67 * 68 * Notes: 69 * Currently uses random address byte read to initiate the read; if 70 * more than one byte of data is requested at the current address, a 71 * sequential read operation is performed. 72 */ 73 STATIC int 74 xfp_read(int unit, int devno, 75 uint16 addr, uint8* data, uint32 *len) 76 { 77 int rv = SOC_E_NONE; 78 uint8 saddr_r, saddr_w, a0; 79 uint32 nbytes = 0; 80 81 /* Valid address, memory and size must be provided */ 82 if ( ! len || ! data ) 83 return SOC_E_PARAM; 84 85 I2C_LOCK(unit); 86 87 saddr_r = SOC_I2C_RX_ADDR(soc_i2c_addr(unit, devno)); 88 saddr_w = SOC_I2C_TX_ADDR(soc_i2c_addr(unit, devno)); 89 90 a0 = (uint8) (addr & 0x00ff); 91 92 LOG_INFO(BSL_LS_SOC_I2C, 93 (BSL_META_U(unit, 94 "xfp_read: addr=0x%x (a0=0x%x) len=%d\n"), 95 addr, a0, (int)*len)); 96 97 /* First, we put out the address which we would like to 98 * read at using the SOC_I2C_TX_ADDR (saddr_w) 99 */ 100 if ( (rv = soc_i2c_start(unit, saddr_w)) < 0) { 101 LOG_INFO(BSL_LS_SOC_I2C, 102 (BSL_META_U(unit, 103 "xfp_read(%d,%d,%x,%p,%d): " 104 "failed to generate start.\n"), 105 unit, devno, addr, (void *)data, *len)); 106 I2C_UNLOCK(unit); 107 return rv; 108 } 109 110 if( (rv = soc_i2c_write_one_byte(unit, a0)) < 0) { 111 LOG_INFO(BSL_LS_SOC_I2C, 112 (BSL_META_U(unit, 113 "xfp_read(%d,%d,%x,%p,%d): " 114 "failed to send a0 byte.\n"), 115 unit, devno, addr, (void *)data, *len)); 116 117 goto error; 118 } 119 /* Now, we have sent the first and second word addresses, 120 * we then issue a repeated start condition, followed by 121 * the device's read address (note: saddr_r) 122 */ 123 if( (rv = soc_i2c_rep_start(unit, saddr_r)) < 0) { 124 LOG_INFO(BSL_LS_SOC_I2C, 125 (BSL_META_U(unit, 126 "xfp_read(%d,%d,%x,%p,%d): " 127 "failed to generate rep start.\n"), 128 unit, devno, addr, (void *)data, *len)); 129 goto error; 130 } 131 nbytes = *len; 132 if ( (rv = soc_i2c_read_bytes(unit, data, (int *)&nbytes, 0) ) < 0 ) { 133 goto error; 134 } 135 *len = nbytes; 136 137 error: 138 139 soc_i2c_stop(unit); 140 141 I2C_UNLOCK(unit); 142 return rv ; 143 } 144 145 /* 146 * Function: xfp_write 147 * Purpose: Write len bytes of data, return the number of bytes written. 148 * Uses PAGE mode to write up to 32 bytes at a time between address 149 * stages for maximum performance. 150 * 151 * Parameters: 152 * unit - StrataSwitch device number or I2C bus number 153 * devno - chip device id 154 * addr - XFP memory address to write to 155 * data - address of data buffer to write from 156 * len - number of bytes to write 157 * 158 * Returns: 159 * SOC_E_NONE -- no error encountered 160 * SOC_E_TIMEOUT - chip timeout or data error 161 * 162 * 163 * Notes: 164 * Uses page mode to write in 32-byte chunks, when an address 165 * which does not begin on a page boundary is provided, the write 166 * operation handles unaligned accesses by breaking up the write 167 * into one write which is not page aligned, and the remainder as 168 * page aligned accesses. 169 */ 170 STATIC int 171 xfp_write(int unit, int devno, 172 uint16 addr, uint8* data, uint32 len) 173 { 174 int rv = SOC_E_NONE; 175 uint8 *ptr, a0; 176 uint32 b, numpages, cpage, nbytes, tbytes, caddr; 177 i2c_bus_addr_t bus_addr; 178 179 /* User must have data to write */ 180 if ( ! data || len <= 0 ) 181 return SOC_E_PARAM; 182 183 I2C_LOCK(unit); 184 185 /* Use PAGE mode */ 186 caddr = addr; 187 numpages = len / XFP_PAGE_SIZE + (len % XFP_PAGE_SIZE > 0); 188 ptr = data; 189 190 191 tbytes = soc_i2c_device(unit, devno)->tbyte++; 192 193 bus_addr = SOC_I2C_TX_ADDR(soc_i2c_addr(unit, devno)); 194 195 LOG_INFO(BSL_LS_SOC_I2C, 196 (BSL_META_U(unit, 197 "xfp_write: addr=0x%x data=%p len=%d npages=%d\n"), 198 caddr, (void *)data, (int)len, numpages)); 199 200 /* Loop over every page in buffer .. */ 201 for(cpage = 0; cpage < numpages; cpage++){ 202 /* Address not page aligned, D'Oh, can't write a full page. */ 203 if( (caddr % XFP_PAGE_SIZE) != 0){ 204 /* coverity[dead_error_begin] */ 205 nbytes = XFP_PAGE_SIZE - (caddr % XFP_PAGE_SIZE); 206 len -= nbytes; 207 } else { 208 /* Address is page aligned, calculate bytes to write */ 209 if ( len <= XFP_PAGE_SIZE ) { 210 /* Less than a page to write */ 211 nbytes = len; 212 } else { 213 /* Wammo, full page write */ 214 nbytes = XFP_PAGE_SIZE; 215 len -= nbytes; 216 } 217 } 218 219 /* Construct device address bytes */ 220 a0 = (uint8) (caddr & 0x00ff); 221 222 LOG_INFO(BSL_LS_SOC_I2C, 223 (BSL_META_U(unit, 224 "xfp_write: unit=%d cpage=%d START on page_addr=0x%x" 225 " nbytes=%d\n"), unit, cpage, caddr, nbytes)); 226 227 /* Generate Start, for Write address */ 228 if( (rv = soc_i2c_start(unit, bus_addr)) < 0){ 229 LOG_INFO(BSL_LS_SOC_I2C, 230 (BSL_META_U(unit, 231 "xfp_write(%d,%d,%x,%d,%d): " 232 "failed to gen start\n"), 233 unit, devno, caddr, *data, len)); 234 I2C_UNLOCK(unit); 235 return rv; 236 } 237 238 /* Send LSB (a0), wait for ACK */ 239 if( (rv = soc_i2c_write_one_byte(unit, a0)) < 0){ 240 LOG_INFO(BSL_LS_SOC_I2C, 241 (BSL_META_U(unit, 242 "xfp_write(%d,%d,%x,%d,%d): " 243 "failed to send a0 byte\n"), 244 unit, devno, caddr, *data, len)); 245 goto error; 246 } 247 /* Send up to PAGE_SIZE data bytes, wait for ACK */ 248 for ( b = 0; b < nbytes; b++, ptr++, caddr++ ) { 249 if ( (rv = soc_i2c_write_one_byte(unit, *ptr)) < 0){ 250 LOG_INFO(BSL_LS_SOC_I2C, 251 (BSL_META_U(unit, 252 "xfp_write(%d,%d,%d,%d,%d): " 253 "tx data byte error\n"), 254 unit, devno, caddr, (uint32)*ptr, b)); 255 goto error; 256 } 257 LOG_VERBOSE(BSL_LS_SOC_I2C, 258 (BSL_META_U(unit, 259 "xfp_write(u=%d,id=%d,page=%d " 260 "caddr=%d,data=0x%x,idx=%d)\n"), 261 unit, devno, cpage, caddr, (uint8)*ptr, b)); 262 263 soc_i2c_device(unit, devno)->tbyte++; 264 } 265 266 /* Send STOP, also what we do on an error to free bus.. */ 267 error: 268 269 soc_i2c_stop(unit); 270 271 /* Acknowledge polling: When the chip enters it's 272 * own internal write-cycle, it falls off the I2C bus 273 * and does not ACK a start/address phase; hence, we 274 * attempt addressing the chip until it responds, at 275 * which point the internal write cycle has finished. 276 */ 277 rv = xfp_ack_poll(unit, bus_addr); 278 LOG_INFO(BSL_LS_SOC_I2C, 279 (BSL_META_U(unit, 280 "xfp_ack_poll: " 281 "%d address cycles for wr latency.\n"), rv)); 282 rv = (rv > 0 ? SOC_E_NONE: SOC_E_TIMEOUT); 283 284 } 285 286 I2C_UNLOCK(unit); 287 288 if (rv >= 0) { 289 return soc_i2c_device(unit, devno)->tbyte - tbytes - 1 ; 290 } else { 291 return (rv); 292 } 293 } 294 295 296 /* 297 * Function: xfp_init 298 * 299 * Purpose: initialize the XFP I2C interface. 300 * 301 * Parameters: 302 * unit - StrataSwitch device number or I2C bus number 303 * devno - chip device id 304 * data - address of test data 305 * len - size of test data 306 */ 307 STATIC int 308 xfp_init(int unit, int devno, void* data, int len) 309 { 310 soc_i2c_devdesc_set(unit, devno, "XFP"); 311 312 return SOC_E_NONE; 313 } 314 315 /* 316 * Function: xfp_ioctl: does miscellaenous tasks. 317 * Purpose: Support miscellaneous chip options. 318 * 319 * Parameters: 320 * unit - StrataSwitch device number or I2C bus number 321 * devno - chip device id 322 * command - IO control operation 323 * data - address of user data 324 * len - size of test data 325 * 326 * Notes: 327 * Placeholder for write Protect, EEPROM Chip reset - NYI 328 */ 329 STATIC int 330 xfp_ioctl(int unit, int devno, 331 int command, void* data, int len) 332 { 333 switch ( command ) { 334 335 default: 336 break; 337 } 338 return SOC_E_NONE; 339 } 340 341 /* XFP Driver callout */ 342 i2c_driver_t _soc_i2c_xfp_driver = { 343 0x0,0x0, /* System assigned bytes */ 344 XFP_DEVICE_TYPE, 345 xfp_read, 346 xfp_write, 347 xfp_ioctl, 348 xfp_init, 349 NULL, 350 };