openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

cxp.c (15087B)


      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 Driver for CXP/QSFP device
      8  *  Derived from XFP driver, more ioctls supported
      9  *  Limited to page 0 
     10  */
     11 #include <shared/bsl.h>
     12 
     13 #include <sal/types.h>
     14 #include <soc/drv.h>
     15 #include <soc/error.h>
     16 #include <soc/debug.h>
     17 #include <soc/i2c.h>
     18 #include <shared/bsl.h>
     19 
     20 #define CXP_PAGE_SIZE            1    /* Bytes per page */
     21 #define CXP_DEVICE_SIZE         (256*CXP_PAGE_SIZE) /* 256 bytes */
     22 #define CXP_ACK_RETRY_COUNT      1000  /* Number of retry polls */
     23 
     24 #define CXP_TX_LOWER_PAGE     0
     25 #define CXP_TX_UPPER_PAGE_0   1
     26 #define CXP_TX_UPPER_PAGE_1   2
     27 #define CXP_RX_LOWER_PAGE     3
     28 #define CXP_RX_UPPER_PAGE_0   4
     29 #define CXP_RX_UPPER_PAGE_1   5
     30 
     31 #define CXP_RX_PAGE_MASK     0x40
     32 #define CXP_UPPER_PAGE_CTRL  0x80
     33 
     34 /*
     35  * Function: cxp_ack_poll
     36  *
     37  * Purpose:  Poll the device to determine if it is ready for IO.
     38  *           When the chip writes data, it will become unresponsive
     39  *           for a period of Time Tw (Internal Write Delay). We could
     40  *           either wait the maximum amount of time for the device to
     41  *           finish it's write-cycle (10ms), or we can poll the device
     42  *           for a specified operation (r/w) until it responds with an
     43  *           ACK. This routine polls the device until it is responsive.
     44  *
     45  * Parameters:
     46  *    unit - StrataSwitch device number or I2C bus number
     47  *    bus_addr - chip IO (I2C) slave bus address byte(s)
     48  *
     49  * Returns:
     50  *     Number of Poll operations required to contact device, or
     51  *     CXP_ACK_RETRY_COUNT if the device is not online or responding.
     52  *
     53  *
     54  * Notes:
     55  *     See also: soc_i2c_ack_poll
     56  */
     57 STATIC INLINE int
     58 cxp_ack_poll(int unit, i2c_bus_addr_t bus_addr)
     59 {
     60     return soc_i2c_ack_poll(unit, bus_addr, CXP_ACK_RETRY_COUNT);
     61 }
     62 
     63 STATIC int
     64 _cxp_read(int unit, uint8 saddr,
     65 	      uint16 addr, uint8* data, uint32 *len)
     66 {
     67     int rv = SOC_E_NONE;
     68     uint8 saddr_r;
     69     uint32 nbytes = 0;
     70     uint8 saddr_w, a0;
     71 
     72     /* Valid address, memory and size must be provided */
     73     if ( ! len || ! data )
     74 	return SOC_E_PARAM;
     75 
     76     I2C_LOCK(unit);
     77 
     78     saddr_r = SOC_I2C_RX_ADDR(saddr);
     79     saddr_w = SOC_I2C_TX_ADDR(saddr);
     80 
     81     a0 = (uint8) (addr & 0x00ff);
     82 
     83     LOG_INFO(BSL_LS_SOC_I2C,
     84              (BSL_META_U(unit,
     85                          "cxp_read: addr=0x%x (a0=0x%x) len=%d\n"),
     86               addr, a0, (int)*len));
     87 
     88     /* First, we put out the address which we would like to
     89      * read at using the SOC_I2C_TX_ADDR (saddr_w)
     90      */
     91     if ( (rv = soc_i2c_start(unit, saddr_w)) < 0) {
     92 	LOG_INFO(BSL_LS_SOC_I2C,
     93                  (BSL_META_U(unit,
     94                              "cxp_read(%d,%x,%x,%p,%d): "
     95                              "failed to generate start.\n"),
     96                   unit, saddr_w, addr, (void *)data, *len));
     97 	I2C_UNLOCK(unit);
     98 	return rv;
     99     }
    100 
    101     if( (rv = soc_i2c_write_one_byte(unit, a0)) < 0) {
    102         LOG_INFO(BSL_LS_SOC_I2C,
    103                  (BSL_META_U(unit,
    104                              "cxp_read(%d,%x,%x,%p,%d): "
    105                              "failed to send a0 byte.\n"),
    106                   unit, saddr_w, addr, (void *)data, *len));
    107 
    108 	goto error;
    109     }
    110     /* Now, we have sent the first and second word addresses,
    111      * we then issue a repeated start condition, followed by
    112      * the device's read address (note: saddr_r)
    113      */
    114     if( (rv = soc_i2c_rep_start(unit, saddr_r)) < 0) {
    115         LOG_INFO(BSL_LS_SOC_I2C,
    116                  (BSL_META_U(unit,
    117                              "cxp_read(%d,%x,%x,%p,%d): "
    118                              "failed to generate rep start.\n"),
    119                   unit, saddr_r, addr, (void *)data, *len));
    120 	goto error;
    121     }
    122     nbytes = *len;
    123     if ( (rv = soc_i2c_read_bytes(unit, data, (int *)&nbytes, 0) ) < 0 ) {
    124 	goto error;
    125     }
    126     *len = nbytes;
    127 
    128  error:
    129 
    130     soc_i2c_stop(unit);
    131 
    132     I2C_UNLOCK(unit);
    133     return rv ;
    134 }
    135 
    136 
    137 /*
    138  * Function: cxp_read
    139  *
    140  * Purpose: Read len bytes of data into buffer, update len with total
    141  *          amount read.
    142  *
    143  * Parameters:
    144  *    unit - StrataSwitch device number or I2C bus number
    145  *    devno - chip device id
    146  *    addr - CXP memory address to read from
    147  *    data - address of data buffer to read into
    148  *    len - address containing number of bytes read into data buffer (updated
    149  *          with number of bytes read on completion).
    150  *
    151  * Returns: data bufffer filled in with data from address, number of
    152  *          bytes read is updated in len field. Status code:
    153  *
    154  *          SOC_E_NONE -- no error encounter
    155  *          SOC_E_TIMEOUT - chip timeout or data error
    156  *
    157  * Notes:
    158  *         Currently uses random address byte read to initiate the read; if
    159  *         more than one byte of data is requested at the current address, a
    160  *         sequential read operation is performed.
    161  */
    162 STATIC int
    163 cxp_read(int unit, int devno,
    164 	      uint16 addr, uint8* data, uint32 *len)
    165 {
    166     int rv;
    167     uint8 saddr;
    168 
    169     saddr = soc_i2c_addr(unit, devno);
    170 
    171     rv = _cxp_read(unit, saddr, addr, data, len);
    172     if (SOC_SUCCESS(rv)) {
    173         soc_i2c_device(unit, devno)->rbyte += *len;
    174     }
    175     return rv;
    176 }
    177 
    178 /*
    179  * Function: cxp_write
    180  * Purpose: Write len bytes of data, return the number of bytes written.
    181  * Uses PAGE mode to write up to 32 bytes at a time between address
    182  * stages for maximum performance.
    183  *
    184  * Parameters:
    185  *    unit - StrataSwitch device number or I2C bus number
    186  *    devno - chip device id
    187  *    addr - CXP memory address to write to
    188  *    data - address of data buffer to write from
    189  *    len - number of bytes to write
    190  *
    191  * Returns:
    192  *          SOC_E_NONE -- no error encountered
    193  *          SOC_E_TIMEOUT - chip timeout or data error
    194  *
    195  *
    196  * Notes:
    197  *     Uses page mode to write in 32-byte chunks, when an address
    198  *     which does not begin on a page boundary is provided, the write
    199  *     operation handles unaligned accesses by breaking up the write
    200  *     into one write which is not page aligned, and the remainder as
    201  *     page aligned accesses.
    202  */
    203 STATIC int
    204 _cxp_write(int unit, uint8 saddr , uint16 addr, uint8* data, uint32 len)
    205 {
    206     int rv = SOC_E_NONE;
    207     i2c_bus_addr_t bus_addr;
    208     uint32 b, numpages, cpage, nbytes, caddr;
    209     uint8 *ptr, a0;
    210 
    211     /* User must have data to write */
    212     if ( ! data || len <= 0 )
    213 	return SOC_E_PARAM;
    214 
    215     I2C_LOCK(unit);
    216 
    217     /* Use PAGE mode */
    218     caddr = addr;
    219     numpages = len / CXP_PAGE_SIZE + (len % CXP_PAGE_SIZE > 0);
    220     ptr = data;
    221 
    222     bus_addr = SOC_I2C_TX_ADDR(saddr);
    223 
    224     LOG_INFO(BSL_LS_SOC_I2C,
    225              (BSL_META_U(unit,
    226                          "cxp_write: addr=0x%x data=%p len=%d npages=%d\n"),
    227               caddr, (void *)data, (int)len, numpages));
    228 
    229     /* Loop over every page in buffer .. */
    230     for(cpage = 0; cpage < numpages; cpage++){
    231 	/* Address not page aligned, D'Oh, can't write a full page. */
    232 	if( (caddr % CXP_PAGE_SIZE) != 0){
    233         /* coverity[dead_error_begin] */
    234 	    nbytes = CXP_PAGE_SIZE - (caddr % CXP_PAGE_SIZE);
    235 	    len -= nbytes;
    236 	} else {
    237 	    /* Address is page aligned, calculate bytes to write */
    238 	    if ( len <= CXP_PAGE_SIZE ) {
    239 	        /* Less than a page to write */
    240 		nbytes = len;
    241 	    } else {
    242 		/* Wammo, full page write */
    243 		nbytes = CXP_PAGE_SIZE;
    244 		len -= nbytes;
    245 	    }
    246 	}
    247 
    248 	/* Construct device address bytes */
    249 	a0 = (uint8) (caddr & 0x00ff);
    250 
    251 	LOG_INFO(BSL_LS_SOC_I2C,
    252                  (BSL_META_U(unit,
    253                              "cxp_write: unit=%d cpage=%d START on page_addr=0x%x"
    254                              " nbytes=%d\n"), unit, cpage, caddr, nbytes));
    255 
    256 	/* Generate Start, for Write address */
    257 	if( (rv = soc_i2c_start(unit, bus_addr)) < 0){
    258 	    LOG_INFO(BSL_LS_SOC_I2C,
    259                      (BSL_META_U(unit,
    260                                  "cxp_write(%d,%x,%x,%d,%d): "
    261                                  "failed to gen start\n"),
    262                       unit, bus_addr, caddr, *data, len));
    263 	    I2C_UNLOCK(unit);
    264 	    return rv;
    265 	}
    266 
    267 	/* Send LSB (a0), wait for ACK */
    268 	if( (rv = soc_i2c_write_one_byte(unit, a0)) < 0){
    269 	    LOG_INFO(BSL_LS_SOC_I2C,
    270                      (BSL_META_U(unit,
    271                                  "cxp_write(%d,%x,%x,%d,%d): "
    272                                  "failed to send a0 byte\n"),
    273                       unit, bus_addr, caddr, *data, len));
    274 	    goto error;
    275 	}
    276 	/* Send up to PAGE_SIZE data bytes, wait for ACK */
    277 	for ( b = 0; b < nbytes; b++, ptr++, caddr++ ) {
    278 	    if ( (rv = soc_i2c_write_one_byte(unit, *ptr)) < 0){
    279             LOG_INFO(BSL_LS_SOC_I2C,
    280                      (BSL_META_U(unit,
    281                                  "cxp_write(%d,%x,%d,%d,%d): "
    282                                  "tx data byte error\n"),
    283                       unit, bus_addr, caddr, (uint32)*ptr, b));
    284 		goto error;
    285 	    }
    286 	    LOG_VERBOSE(BSL_LS_SOC_I2C,
    287                         (BSL_META_U(unit,
    288                                     "cxp_write(u=%d,addr=%x,page=%d "
    289                                     "caddr=%d,data=0x%x,idx=%d)\n"),
    290                          unit, bus_addr, cpage, caddr, (uint8)*ptr, b));
    291 
    292 	}
    293 
    294 	/* Send STOP, also what we do on an error to free bus.. */
    295     error:
    296 
    297 	soc_i2c_stop(unit);
    298 
    299 	/* Acknowledge polling: When the chip enters it's
    300 	 * own internal write-cycle, it falls off the I2C bus
    301 	 * and does not ACK a start/address phase; hence, we
    302 	 * attempt addressing the chip until it responds, at
    303 	 * which point the internal write cycle has finished.
    304 	 */
    305 	rv = cxp_ack_poll(unit, bus_addr);
    306 	LOG_INFO(BSL_LS_SOC_I2C,
    307                  (BSL_META_U(unit,
    308                              "cxp_ack_poll: "
    309                              "%d address cycles for wr latency.\n"), rv));
    310 	rv = (rv > 0 ? SOC_E_NONE: SOC_E_TIMEOUT);
    311 
    312     }
    313 
    314     I2C_UNLOCK(unit);
    315     return (rv);
    316 }
    317 
    318 STATIC int
    319 cxp_write(int unit, int devno, 
    320 	      uint16 addr, uint8* data, uint32 len)
    321 {
    322     uint8 saddr;
    323     int rv;
    324 
    325     saddr = soc_i2c_addr(unit, devno);
    326 
    327     rv = _cxp_write(unit, saddr, addr, data, len);
    328     if (SOC_SUCCESS(rv)) {
    329         soc_i2c_device(unit, devno)->tbyte += len;
    330     }
    331     return rv;
    332 }
    333 
    334 
    335 /*
    336  * Function: cxp_ioctl: does miscellaenous tasks.
    337  * Purpose: Support miscellaneous chip options.
    338  *
    339  * Parameters:
    340  *    unit - StrataSwitch device number or I2C bus number
    341  *    devno - chip device id
    342  *    command - IO control operation
    343  *    data - address of user data
    344  *    len - size of test data
    345  *
    346  * Notes:
    347  *   Placeholder for write Protect, EEPROM Chip reset - NYI
    348  */
    349 STATIC int
    350 cxp_ioctl(int unit, int devno,
    351 	       int command, void* data, int wlen)
    352 {
    353     int offset = 0, page = 0;
    354     uint32 len = 1;
    355     int op = 0; /* read */
    356     uint8 saddr;
    357     uint8 cxp_dev = 1;
    358 
    359     saddr = soc_i2c_addr(unit, devno);
    360 
    361     _cxp_read(unit, saddr, 128, (uint8*)&cxp_dev, &len);
    362     switch ( command ) {
    363     case I2C_CXP_VENDOR_NAME:
    364         page = 0;
    365         if (cxp_dev == 0xc) { offset = 148; }
    366         else if (cxp_dev < 0xc) { offset = 20; }
    367         else { offset = 152; page = CXP_TX_UPPER_PAGE_0;}
    368         len = 16;
    369         break;
    370     case I2C_CXP_VENDOR_OUI:
    371         offset = 168;
    372         page = CXP_TX_UPPER_PAGE_0;
    373         len = 3;
    374         break;
    375     case I2C_CXP_VENDOR_PART_NUM:
    376         page = 0;
    377         if (cxp_dev == 0xc) { offset = 162; }
    378         else if (cxp_dev < 0xc) { offset = 40; }
    379         else { offset = 171; page = CXP_TX_UPPER_PAGE_0;}
    380         len = 16;
    381         break;
    382     case I2C_CXP_VENDOR_REV_ID:
    383         offset = 187;
    384         page = CXP_TX_UPPER_PAGE_0;
    385         len = 2;
    386         break;
    387     case I2C_CXP_VENDOR_SERIAL:
    388         offset = 189;
    389         page = CXP_TX_UPPER_PAGE_0;
    390         len = 16;
    391         break;
    392     case I2C_CXP_VENDOR_DATE:
    393         offset = 205;
    394         page = CXP_TX_UPPER_PAGE_0;
    395         len = 8;
    396         break;
    397     case I2C_CXP_VENDOR_LOT:
    398         offset = 213;
    399         page = CXP_TX_UPPER_PAGE_0;
    400         len = 10;
    401         break;
    402     case I2C_CXP_TX_CAPABILITY:
    403         offset = 142;
    404         page = CXP_TX_UPPER_PAGE_0;
    405         len = 2;
    406         break;
    407     case I2C_CXP_RX_CAPABILITY:
    408         offset = 144 ;
    409         page = CXP_RX_UPPER_PAGE_0;
    410         len = 2;
    411         break;
    412     case I2C_CXP_RX_STATUS:
    413         page = CXP_RX_LOWER_PAGE;
    414         offset = 6;
    415         len = 1;
    416         break;
    417     case I2C_CXP_RX_LOS_STATUS:
    418         /* returns both LOS and FAULT */
    419         page = CXP_RX_LOWER_PAGE;
    420         offset = 7;
    421         len = 4;
    422         break;
    423     case I2C_CXP_RX_CHANNEL_CTRL:
    424         page = CXP_RX_LOWER_PAGE;
    425         offset = 52;
    426         len = 2;
    427         break;
    428     case I2C_CXP_RX_OUTPUT_CTRL:
    429         page = CXP_RX_LOWER_PAGE;
    430         offset = 54;
    431         len = 2;
    432         op = 1;
    433         break;
    434     case I2C_CXP_RX_OUTPUT_STATUS:
    435         page = CXP_RX_LOWER_PAGE;
    436         offset = 54;
    437         len = 2;
    438         break;
    439     case I2C_CXP_RX_LOS_MASK:
    440         page = CXP_RX_LOWER_PAGE;
    441         offset = 95;
    442         len = 2;
    443         break;
    444 
    445     case I2C_CXP_TX_STATUS:
    446         page = CXP_TX_LOWER_PAGE;
    447         offset = 6;
    448         len = 1;
    449         break;
    450     case I2C_CXP_TX_LOS_STATUS:
    451         /* returns both LOS and FAULT */
    452         page = CXP_TX_LOWER_PAGE;
    453         offset = 7;
    454         len = 4;
    455         break;
    456     case I2C_CXP_TX_CHANNEL_CTRL:
    457         page = CXP_TX_LOWER_PAGE;
    458         offset = 52;
    459         len = 2;
    460         break;
    461     case I2C_CXP_TX_OUTPUT_CTRL:
    462         page = CXP_TX_LOWER_PAGE;
    463         offset = 54;
    464         len = 2;
    465         op = 1;
    466         break;
    467     case I2C_CXP_TX_OUTPUT_STATUS:
    468         page = CXP_TX_LOWER_PAGE;
    469         offset = 54;
    470         len = 2;
    471         break;
    472     case I2C_CXP_TX_LOS_MASK:
    473         page = CXP_TX_LOWER_PAGE;
    474         offset = 95;
    475         len = 2;
    476         break;
    477     default:
    478 	break;
    479     }
    480     saddr = soc_i2c_addr(unit, devno);
    481     if (page >= CXP_RX_LOWER_PAGE) {
    482         saddr |= CXP_RX_PAGE_MASK;
    483     }
    484     if (op) {
    485         _cxp_write(unit, saddr, offset, (uint8*)data, len);
    486     } else {
    487         _cxp_read(unit, saddr, offset, (uint8*)data, &len);
    488     }
    489     return SOC_E_NONE;
    490 }
    491 
    492 /*
    493  * Function: cxp_init
    494  *
    495  * Purpose: initialize the CXP I2C interface.
    496  *
    497  * Parameters:
    498  *    unit - StrataSwitch device number or I2C bus number
    499  *    devno - chip device id
    500  *    data - address of test data
    501  *    len - size of test data
    502  */
    503 STATIC int
    504 cxp_init(int unit, int devno, void* data, int len)
    505 {
    506     uint8 buffer[256];
    507     sal_memset(buffer, 0, 256);
    508     cxp_ioctl(unit, devno, I2C_CXP_VENDOR_NAME, buffer, 256);
    509     LOG_VERBOSE(BSL_LS_SOC_I2C,
    510                 (BSL_META_U(unit,
    511                             "\nCXP device: Vendor name: %s"), buffer));
    512     sal_memset(buffer, 0, 256);
    513     cxp_ioctl(unit, devno, I2C_CXP_VENDOR_PART_NUM, buffer, 256);
    514     LOG_VERBOSE(BSL_LS_SOC_I2C,
    515                 (BSL_META_U(unit,
    516                             "Part: %s detected \n"), buffer));
    517 
    518     soc_i2c_devdesc_set(unit, devno, "Cxp/Sfp/Qsfp Driver");
    519 
    520     return SOC_E_NONE;
    521 }
    522 
    523 
    524 /* CXP Driver callout */
    525 i2c_driver_t _soc_i2c_cxp_driver = {
    526     0x0,0x0, /* System assigned bytes */
    527     CXP_DEVICE_TYPE,
    528     cxp_read,
    529     cxp_write,
    530     cxp_ioctl,
    531     cxp_init,
    532     NULL,
    533 };