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

pcie.c (11684B)


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