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