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

mspi.c (9603B)


      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:        mspi.c
      8  * Purpose:     SPI Master mode Implementation
      9  * Requires:    
     10  */
     11 
     12 #include <shared/bsl.h>
     13 
     14 #include <sal/core/boot.h>
     15 #include <sal/core/libc.h>
     16 #include <shared/alloc.h>
     17 
     18 #include <soc/drv.h>
     19 #include <soc/debug.h>
     20 #include <soc/cm.h>
     21 #include <soc/mspi.h>
     22 #include <soc/cmicm.h>
     23 
     24 #ifdef BCM_CMICM_SUPPORT
     25 
     26 int soc_mspi_init(int unit) {
     27     uint32 rval;
     28 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)
     29     uint32 fval;
     30 #endif /* BCM_KATANA_SUPPORT || BCM_TRIUMPH3_SUPPORT || BCM_TRIDENT2_SUPPORT */
     31 
     32     if (!soc_feature(unit, soc_feature_cmicm)) {
     33         return SOC_E_FAIL;
     34     }
     35 
     36     /* Claim the SPI bus */
     37     READ_CMIC_OVERRIDE_STRAPr(unit, &rval);
     38     soc_reg_field_set(unit, CMIC_OVERRIDE_STRAPr, &rval, ENABLE_OVERRIDE_SPI_MASTER_SLAVE_MODEf, 1);
     39     soc_reg_field_set(unit, CMIC_OVERRIDE_STRAPr, &rval, SPI_MASTER_SLAVE_MODEf, 1);
     40     WRITE_CMIC_OVERRIDE_STRAPr(unit, rval);
     41 
     42     READ_CMICM_BSPI_MAST_N_BOOTr(unit, &rval);
     43     soc_reg_field_set(unit, CMICM_BSPI_MAST_N_BOOTr, &rval, MAST_N_BOOTf, 1);
     44     WRITE_CMICM_BSPI_MAST_N_BOOTr(unit, rval);
     45 
     46     /* 
     47      * Set speed and transfer size
     48      */
     49     READ_MSPI_SPCR0_LSBr(unit, &rval);
     50     soc_reg_field_set(unit, MSPI_SPCR0_LSBr, &rval, SPBRf, 0x08);
     51     WRITE_MSPI_SPCR0_LSBr(unit, rval);
     52 
     53 #if 0
     54     READ_MSPI_SPCR0_MSBr(unit, &rval);
     55     rval |= 0x08 << 2; /* Bits per transfer - BITS = 0x08 */
     56     WRITE_MSPI_SPCR0_MSBr(unit, rval);
     57 #endif
     58 
     59     READ_MSPI_SPCR1_LSBr(unit, &rval);
     60     rval |= 0x01;  /* Delay after transfer- DTL = 0x01 */
     61     WRITE_MSPI_SPCR1_LSBr(unit, rval);
     62 
     63     READ_MSPI_SPCR1_MSBr(unit, &rval);
     64     rval |= 0x01;  /* DSCLK = 0x01 */
     65     WRITE_MSPI_SPCR1_MSBr(unit, rval);
     66 
     67 #ifdef BCM_KATANA_SUPPORT
     68     if (SOC_IS_KATANA(unit)) {
     69         /* For Now, Hard code GPIO2 and GPIO3 as Output for SPI_CS_SEL */
     70         /* coverity[result_independent_of_operands] */           
     71         SOC_IF_ERROR_RETURN(READ_CMIC_GP_OUT_ENr(unit,&rval));
     72         fval = soc_reg_field_get(unit, CMIC_GP_OUT_ENr, rval, OUT_ENABLEf);
     73         fval |= 0xc;
     74         soc_reg_field_set(unit, CMIC_GP_OUT_ENr, &rval, OUT_ENABLEf, fval);
     75         /* coverity[result_independent_of_operands] */           
     76         SOC_IF_ERROR_RETURN(WRITE_CMIC_GP_OUT_ENr(unit,rval));
     77     }
     78 #endif /* BCM_KATANA_SUPPORT */
     79 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)
     80     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2(unit)) {
     81         /* Drive GPIO1 high for SPI_CS_SEL */
     82         /* coverity[result_independent_of_operands] */           
     83         SOC_IF_ERROR_RETURN(READ_CMIC_GP_OUT_ENr(unit,&rval));
     84         fval = soc_reg_field_get(unit, CMIC_GP_OUT_ENr, rval, OUT_ENABLEf);
     85         fval |= 0x2;
     86         soc_reg_field_set(unit, CMIC_GP_OUT_ENr, &rval, OUT_ENABLEf, fval);
     87         /* coverity[result_independent_of_operands] */           
     88         SOC_IF_ERROR_RETURN(WRITE_CMIC_GP_OUT_ENr(unit,rval));
     89     }
     90 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_TRIDENT2_SUPPORT */
     91 
     92     return SOC_E_NONE;
     93 }
     94 
     95 int soc_mspi_config(int unit, int device, int cpol, int cpha) {
     96     uint32 rval;
     97 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)
     98     uint32 fval;
     99     int selval;
    100 #endif /* BCM_KATANA_SUPPORT || BCM_TRIUMPH3_SUPPORT || BCM_TRIDENT2_SUPPORT */
    101     if (!soc_feature(unit, soc_feature_cmicm)) {
    102         return SOC_E_FAIL;
    103     }
    104 #ifdef BCM_KATANA_SUPPORT
    105     if (SOC_IS_KATANA(unit)) {
    106         if(device != -1) {
    107             /* Set GPIOs Outputs accordingly */
    108             switch (device) {
    109                 case MSPI_FLASH:
    110                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    111                                 (BSL_META_U(unit,
    112                                             "MSPI: Selecting Flash\n")));
    113                     selval = 0;
    114                     break;
    115                 case MSPI_LIU:
    116                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    117                                 (BSL_META_U(unit,
    118                                             "MSPI: Selecting LIU\n")));
    119                     selval = 1;
    120                     break;
    121                 case MSPI_DPLL:
    122                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    123                                 (BSL_META_U(unit,
    124                                             "MSPI: Selecting DPLL\n")));
    125                     selval = 2;
    126                     break;
    127                 case MSPI_EXTRA:
    128                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    129                                 (BSL_META_U(unit,
    130                                             "MSPI: Selecting Extra Mux\n")));
    131                     selval = 3;
    132                     break;
    133                 default:
    134                     /* What Device? */
    135                     return SOC_E_PARAM;
    136             }
    137             /* coverity[result_independent_of_operands] */           
    138             SOC_IF_ERROR_RETURN(READ_CMIC_GP_DATA_OUTr(unit,&rval));
    139             fval = soc_reg_field_get(unit, CMIC_GP_DATA_OUTr, rval, DATA_OUTf);
    140             fval &= 0x3;
    141             fval |= (selval<<2);
    142             soc_reg_field_set(unit, CMIC_GP_DATA_OUTr, &rval, DATA_OUTf, fval);
    143             /* coverity[result_independent_of_operands] */           
    144             SOC_IF_ERROR_RETURN(WRITE_CMIC_GP_DATA_OUTr(unit,rval));
    145         }
    146     }
    147 #endif /* BCM_KATANA_SUPPORT */
    148 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)
    149     if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT2(unit)) {
    150         if(device != -1) {
    151             /* Set GPIOs Outputs accordingly */
    152             switch (device) {
    153                 case MSPI_DPLL:
    154                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    155                                 (BSL_META_U(unit,
    156                                             "MSPI: Selecting Flash\n")));
    157                     selval = 1;
    158                     break;
    159                 case MSPI_EXTRA:
    160                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    161                                 (BSL_META_U(unit,
    162                                             "MSPI: Selecting DPLL\n")));
    163                     selval = 0;
    164                     break;
    165                 default:
    166                     /* What Device? */
    167                     return SOC_E_PARAM;
    168             }
    169             /* coverity[result_independent_of_operands] */           
    170             SOC_IF_ERROR_RETURN(READ_CMIC_GP_DATA_OUTr(unit,&rval));
    171             fval = soc_reg_field_get(unit, CMIC_GP_DATA_OUTr, rval, DATA_OUTf);
    172             fval &= 0xd;
    173             fval |= (selval<<1);
    174             soc_reg_field_set(unit, CMIC_GP_DATA_OUTr, &rval, DATA_OUTf, fval);
    175             /* coverity[result_independent_of_operands] */           
    176             SOC_IF_ERROR_RETURN(WRITE_CMIC_GP_DATA_OUTr(unit,rval));
    177         }
    178     }
    179 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_TRIDENT2_SUPPORT */
    180     if ((cpol != -1) || (cpha != -1)) {
    181         /* coverity[result_independent_of_operands] */           
    182         SOC_IF_ERROR_RETURN(READ_MSPI_SPCR0_MSBr(unit, &rval));
    183         if(cpol != -1) {
    184             soc_reg_field_set(unit, MSPI_SPCR0_MSBr, &rval, CPOLf, (cpol ? 1 : 0));
    185         }
    186         if(cpha != -1) {
    187             soc_reg_field_set(unit, MSPI_SPCR0_MSBr, &rval, CPHAf, (cpha ? 1 : 0));
    188         }
    189         /* coverity[result_independent_of_operands] */           
    190         SOC_IF_ERROR_RETURN(WRITE_MSPI_SPCR0_MSBr(unit, rval));
    191     }
    192 
    193     return SOC_E_NONE;
    194 }
    195 
    196 int soc_mspi_writeread8(int unit, uint8 *wbuf, int wlen, uint8 *rbuf, int rlen)
    197 {
    198     int i, tlen, rv = SOC_E_TIMEOUT;
    199     uint8 *datptr;
    200     uint32 rval=0;
    201     soc_timeout_t to;
    202 
    203     if (!soc_feature(unit, soc_feature_cmicm)) {
    204         return SOC_E_FAIL;
    205     }
    206 
    207     
    208     READ_MSPI_SPCR0_LSBr(unit, &rval);
    209     soc_reg_field_set(unit, MSPI_SPCR0_LSBr, &rval, SPBRf, 0x08);
    210     WRITE_MSPI_SPCR0_LSBr(unit, rval);
    211 
    212     WRITE_MSPI_STATUSr(unit, 0);
    213 
    214     tlen = wlen + rlen;
    215     if (tlen > 16) {
    216         return SOC_E_PARAM;
    217     }
    218     if ((wbuf != NULL) && (wlen > 0)) {
    219         datptr = wbuf;
    220         for (i=0; i<wlen; i++) {
    221             /* Use only Even index of TXRAM for 8 bit xmit */
    222             soc_pci_write(unit, MSPI_TXRAM_nn((2*i)), (uint32) *datptr);
    223             datptr++;
    224         }
    225     }
    226 
    227     for (i=0; i<tlen; i++) {
    228         /* Release CS ony on last byute */
    229         soc_pci_write(unit, MSPI_CDRAM_nn(i), (i == (tlen-1)) ? 0 : 0x80);
    230     }
    231     /* Set queue pointers */
    232     WRITE_MSPI_NEWQPr(unit,0);
    233     WRITE_MSPI_ENDQPr(unit,(tlen-1));
    234 
    235     /* Start SPI transfer */
    236     rval = 0x40; /* SPE=1, SPIFIE=WREN=WRT0=LOOPQ=HIE=HALT=0 */
    237     WRITE_MSPI_SPCR2r(unit,rval);
    238 
    239     soc_timeout_init(&to, 10000, 1000);
    240     
    241     do {
    242         READ_MSPI_STATUSr(unit,&rval);
    243         if (soc_reg_field_get(unit, MSPI_STATUSr,rval, SPIFf)) {
    244             rv = SOC_E_NONE;
    245             break;
    246         }
    247     } while(!(soc_timeout_check(&to)));
    248 
    249     if (rv == SOC_E_TIMEOUT) {
    250         return SOC_E_TIMEOUT;
    251     }
    252 
    253     if ((rbuf != NULL) && (rlen > 0)) {
    254         datptr = rbuf;
    255         for (i=wlen; i<tlen; i++) {
    256             /* Use only Odd index of TXRAM for 8 bit Recv */
    257             *datptr = (uint8) (soc_pci_read(unit, MSPI_RXRAM_nn(((2*i)+1))) & 0xff);
    258             datptr++;
    259         }
    260     }
    261     return SOC_E_NONE;
    262 }
    263 
    264 int soc_mspi_read8(int unit, uint8 *buf, int len)
    265 {
    266     return  soc_mspi_writeread8(unit, NULL, 0, buf, len);
    267 }
    268 
    269 int soc_mspi_write8(int unit, uint8 *buf, int len)
    270 {
    271     return  soc_mspi_writeread8(unit, buf, len, NULL, 0);
    272 }
    273 
    274 #endif /* ifdef BCM_CMICM_SUPPORT */    
    275