| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | /****************************************************************************** |
| 2 | * |
| 3 | * (C)Copyright 2014 Marvell Hefei Branch. All Rights Reserved. |
| 4 | * |
| 5 | * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL. |
| 6 | * The copyright notice above does not evidence any actual or intended |
| 7 | * publication of such source code. |
| 8 | * This Module contains Proprietary Information of Marvell and should be |
| 9 | * treated as Confidential. |
| 10 | * The information in this file is provided for the exclusive use of the |
| 11 | * licensees of Marvell. |
| 12 | * Such users have the right to use, modify, and incorporate this code into |
| 13 | * products for purposes authorized by the license agreement provided they |
| 14 | * include this notice and the associated copyright notice with any such |
| 15 | * product. |
| 16 | * The information in this file is provided "AS IS" without warranty. |
| 17 | * |
| 18 | ******************************************************************************/ |
| 19 | |
| 20 | #include "SPINOR_extened.h" |
| 21 | |
| 22 | extern __attribute__ ((aligned(16))) XLLP_DMAC_DESCRIPTOR_T pRX_data, pTX_cmd; |
| 23 | extern VUINT_T ssp_52mhz; |
| 24 | extern UINT_T Spansion_SPINOR_Flash; |
| 25 | __attribute__ ((aligned(16)))unsigned char tx_command_spinor[SIZE_4KB] = {0}; |
| 26 | extern UINT_T spi_tx_dma, spi_rx_dma; |
| 27 | |
| 28 | unsigned int Extend_Read(unsigned int Offset, unsigned int Buffer, unsigned int Size) |
| 29 | { |
| 30 | unsigned int i; |
| 31 | DMA_CMDx_T RX_data, TX_cmd; |
| 32 | UINT8_T data[5]; |
| 33 | |
| 34 | unsigned int * buff = (unsigned int *) Buffer; |
| 35 | |
| 36 | P_SPINOR_T spinor_info = getSPINor_Info(); |
| 37 | |
| 38 | tx_command_spinor[0] = spinor_info->read_4bytes_cmd; |
| 39 | tx_command_spinor[1] = (Offset >> 24) & 0xFF; |
| 40 | tx_command_spinor[2] = (Offset >> 16) & 0xFF; |
| 41 | tx_command_spinor[3] = (Offset >> 8) & 0xFF; |
| 42 | tx_command_spinor[4] = (Offset >> 0) & 0xFF; |
| 43 | |
| 44 | |
| 45 | //fill out commands |
| 46 | RX_data.value = 0; |
| 47 | RX_data.bits.IncTrgAddr = 1; |
| 48 | RX_data.bits.FlowSrc = 1; |
| 49 | RX_data.bits.Width = 3; |
| 50 | RX_data.bits.MaxBurstSize = 2; |
| 51 | |
| 52 | TX_cmd.value = 0; |
| 53 | TX_cmd.bits.IncSrcAddr = 1; |
| 54 | TX_cmd.bits.FlowTrg = 1; |
| 55 | TX_cmd.bits.Width = 3; |
| 56 | TX_cmd.bits.MaxBurstSize = 2; |
| 57 | |
| 58 | //Map Device to Channels |
| 59 | XllpDmacMapDeviceToChannel(spi_rx_dma, SSP_RX_CHANNEL); |
| 60 | XllpDmacMapDeviceToChannel(spi_tx_dma, SSP_TX_CHANNEL); |
| 61 | |
| 62 | //turn ON user alignment - in case buffer address is 64bit aligned |
| 63 | alignChannel(SSP_RX_CHANNEL, 1); |
| 64 | |
| 65 | // * configure RX & TX descriptors * // |
| 66 | configDescriptor(&pRX_data, NULL, (unsigned int)SSP_DR, (unsigned int)Buffer, &RX_data, Size, 1); |
| 67 | configDescriptor(&pTX_cmd, |
| 68 | NULL, |
| 69 | (unsigned int)&tx_command_spinor[0], |
| 70 | (unsigned int)SSP_DR, |
| 71 | &TX_cmd, |
| 72 | Size, |
| 73 | 1); |
| 74 | |
| 75 | //Load descriptors |
| 76 | loadDescriptor (&pRX_data, SSP_RX_CHANNEL); |
| 77 | loadDescriptor (&pTX_cmd, SSP_TX_CHANNEL); |
| 78 | |
| 79 | SPI_DisableSSP(); |
| 80 | |
| 81 | // workaround for 52MHz SPI bit shift |
| 82 | if (ssp_52mhz) |
| 83 | reg_bit_set(SSP_CR0, SSP_SSCR0_52MM); |
| 84 | //setup for DMA: TX and RX DMA request + DMA handles Trailing bytes |
| 85 | reg_bit_set(SSP_CR1, SSP_SSCR1_TRAIL | |
| 86 | SSP_SSCR1_TSRE | |
| 87 | SSP_SSCR1_RSRE | |
| 88 | SSP_SSCR1_TINTE| |
| 89 | (8 << SSP_SSCR1_TFT_BASE) | // TFT: 3 |
| 90 | (3 << SSP_SSCR1_RFT_BASE)); // RFT: 4 |
| 91 | |
| 92 | reg_write(SSP_TO, 0x400); |
| 93 | |
| 94 | #if ENABLE_MMU |
| 95 | dcache_clean_range(&pRX_data, sizeof(XLLP_DMAC_DESCRIPTOR_T)); |
| 96 | dcache_clean_range(&pTX_cmd, sizeof(XLLP_DMAC_DESCRIPTOR_T)); |
| 97 | dcache_clean_range(&tx_command_spinor[0], sizeof(tx_command_spinor)); |
| 98 | dcache_invalidate_range(Buffer, Size); |
| 99 | #endif |
| 100 | |
| 101 | //fire it up |
| 102 | reg_bit_set(SSP_CR0, SSP_CR0_SSE); |
| 103 | |
| 104 | Assert_CS(); |
| 105 | |
| 106 | SPI_Write_Read(tx_command_spinor, data, 5); |
| 107 | |
| 108 | SPI_DisableSSP(); |
| 109 | |
| 110 | //setup in 32 bit mode |
| 111 | reg_bit_set(SSP_CR0, SSP_CR0_DSS_32); |
| 112 | |
| 113 | // workaround for 52MHz SPI bit shift |
| 114 | if (ssp_52mhz) |
| 115 | reg_bit_set(SSP_CR0, SSP_SSCR0_52MM); |
| 116 | //setup for DMA: TX and RX DMA request |
| 117 | reg_bit_set(SSP_CR1, SSP_SSCR1_TRAIL | |
| 118 | SSP_SSCR1_TSRE | |
| 119 | SSP_SSCR1_RSRE | |
| 120 | SSP_SSCR1_TINTE| |
| 121 | (8 << SSP_SSCR1_TFT_BASE) | // TFT: 3 |
| 122 | (3 << SSP_SSCR1_RFT_BASE)); // RFT: 4 |
| 123 | |
| 124 | reg_write(SSP_TO, 0x400); |
| 125 | |
| 126 | //fire it up |
| 127 | reg_bit_set(SSP_CR0, SSP_CR0_SSE); |
| 128 | |
| 129 | //Kick off DMA's |
| 130 | XllpDmacStartTransfer(SSP_TX_CHANNEL); |
| 131 | XllpDmacStartTransfer(SSP_RX_CHANNEL); |
| 132 | |
| 133 | //wait until the RX channel gets the stop interrupt |
| 134 | while( (readDmaStatusRegister(SSP_RX_CHANNEL) & XLLP_DMAC_DCSR_STOP_INTR) != XLLP_DMAC_DCSR_STOP_INTR ) |
| 135 | ROW_DELAY(DEFAULT_TIMEOUT); |
| 136 | |
| 137 | while( (readDmaStatusRegister(SSP_TX_CHANNEL) & XLLP_DMAC_DCSR_STOP_INTR) != XLLP_DMAC_DCSR_STOP_INTR ) |
| 138 | ROW_DELAY(DEFAULT_TIMEOUT); |
| 139 | |
| 140 | SPI_WaitSSPComplete(); |
| 141 | |
| 142 | Deassert_CS(); |
| 143 | |
| 144 | SPI_DisableSSP(); |
| 145 | |
| 146 | //clear out DMA settings |
| 147 | XllpDmacUnMapDeviceToChannel(spi_rx_dma, SSP_RX_CHANNEL); |
| 148 | XllpDmacUnMapDeviceToChannel(spi_tx_dma, SSP_TX_CHANNEL); |
| 149 | |
| 150 | //postprocessing... endian convert |
| 151 | Size >>= 2; //convert Size from bytes to words |
| 152 | for(i = 0; i < Size; i++) |
| 153 | buff[i] = Endian_Convert(buff[i]); |
| 154 | |
| 155 | return NoError; |
| 156 | } |
| 157 | |
| 158 | UINT_T SPINOR_Extend_Read(UINT_T FlashOffset, UINT_T Buffer, UINT_T Size) |
| 159 | { |
| 160 | UINT_T Retval, i, total_size, read_size, status; |
| 161 | |
| 162 | do { |
| 163 | |
| 164 | read_size = Size > SIZE_4KB ? SIZE_4KB : Size; |
| 165 | |
| 166 | Retval = Extend_Read(FlashOffset, Buffer, SIZE_4KB); |
| 167 | |
| 168 | //update counters |
| 169 | FlashOffset+=read_size; |
| 170 | Buffer+=read_size; |
| 171 | Size-=read_size; |
| 172 | |
| 173 | } while( (Size > 0) && (Retval == NoError) ); |
| 174 | |
| 175 | return Retval; |
| 176 | } |
| 177 | |
| 178 | unsigned int Extend_Write(unsigned int Address, unsigned int Buffer, unsigned int Size) |
| 179 | { |
| 180 | unsigned int i; |
| 181 | DMA_CMDx_T TX_data; |
| 182 | unsigned char cmd[5], data[5]; |
| 183 | P_SPINOR_T spinor_info = getSPINor_Info(); |
| 184 | unsigned int convert_size = Size; |
| 185 | |
| 186 | unsigned int * convert_buff = NULL; |
| 187 | unsigned int * orginal_buff = (unsigned int *) Buffer; |
| 188 | |
| 189 | convert_buff = (unsigned int *) malloc(Size); |
| 190 | if(convert_buff == NULL) |
| 191 | return HeapExhaustedError; |
| 192 | |
| 193 | #if 1 |
| 194 | //postprocessing... endian convert |
| 195 | convert_size >>= 2; //convert Size from bytes to words |
| 196 | for(i = 0; i < convert_size; i++) |
| 197 | convert_buff[i] = Endian_Convert(orginal_buff[i]); |
| 198 | |
| 199 | cmd[0] = spinor_info->write_4bytes_cmd; |
| 200 | cmd[1] = (Address >> 24) & 0xFF; |
| 201 | cmd[2] = (Address >> 16) & 0xFF; |
| 202 | cmd[3] = (Address >> 8) & 0xFF; |
| 203 | cmd[4] = (Address >> 0) & 0xFF; |
| 204 | |
| 205 | TX_data.value = 0; |
| 206 | TX_data.bits.IncSrcAddr = 1; |
| 207 | TX_data.bits.FlowTrg = 1; |
| 208 | TX_data.bits.Width = 3; |
| 209 | TX_data.bits.MaxBurstSize = 2; |
| 210 | TX_data.bits.Length = Size; |
| 211 | |
| 212 | //setup DMA |
| 213 | //Map Device to Channels |
| 214 | XllpDmacMapDeviceToChannel(spi_tx_dma, SSP_TX_CHANNEL); |
| 215 | XllpDmacNoDescriptorFetch( SSP_TX_CHANNEL ); |
| 216 | |
| 217 | //turn ON user alignment - in case buffer address is 64bit aligned |
| 218 | alignChannel(SSP_TX_CHANNEL, 1); |
| 219 | |
| 220 | loadNonDescriptor((unsigned int)convert_buff, (unsigned int) SSP_DR, &TX_data, SSP_TX_CHANNEL); |
| 221 | |
| 222 | SPI_DisableSSP(); |
| 223 | |
| 224 | // workaround for 52MHz SPI bit shift |
| 225 | if (ssp_52mhz) |
| 226 | reg_bit_set(SSP_CR0, SSP_SSCR0_52MM); |
| 227 | //setup for DMA: TX and RX DMA request |
| 228 | reg_bit_set(SSP_CR1, SSP_SSCR1_TRAIL | |
| 229 | SSP_SSCR1_TSRE | |
| 230 | SSP_SSCR1_RSRE | |
| 231 | SSP_SSCR1_TINTE| |
| 232 | (3 << SSP_SSCR1_TFT_BASE) | |
| 233 | (4 << SSP_SSCR1_RFT_BASE)); |
| 234 | |
| 235 | reg_write(SSP_TO, 0x400); |
| 236 | |
| 237 | //fire it up |
| 238 | reg_bit_set(SSP_CR0, SSP_CR0_SSE); |
| 239 | |
| 240 | Assert_CS(); |
| 241 | |
| 242 | SPI_Write_Read(cmd, data, sizeof(cmd)); |
| 243 | |
| 244 | SPI_DisableSSP(); |
| 245 | |
| 246 | //setup in 32 bit mode |
| 247 | reg_bit_set(SSP_CR0, SSP_CR0_DSS_32); |
| 248 | |
| 249 | // workaround for 52MHz SPI bit shift |
| 250 | if (ssp_52mhz) |
| 251 | reg_bit_set(SSP_CR0, SSP_SSCR0_52MM); |
| 252 | //setup for DMA: TX and RX DMA request |
| 253 | reg_bit_set(SSP_CR1, SSP_SSCR1_TRAIL | |
| 254 | SSP_SSCR1_TSRE | |
| 255 | SSP_SSCR1_RSRE | |
| 256 | SSP_SSCR1_TINTE| |
| 257 | (3 << SSP_SSCR1_TFT_BASE) | |
| 258 | (4 << SSP_SSCR1_RFT_BASE)); |
| 259 | |
| 260 | reg_write(SSP_TO, 0x400); |
| 261 | |
| 262 | //fire it up |
| 263 | reg_bit_set(SSP_CR0, SSP_CR0_SSE); |
| 264 | |
| 265 | //Kick off DMA's |
| 266 | XllpDmacStartTransfer(SSP_TX_CHANNEL); |
| 267 | |
| 268 | //wait until the RX channel gets the stop interrupt |
| 269 | while( (readDmaStatusRegister(SSP_TX_CHANNEL) & XLLP_DMAC_DCSR_STOP_INTR) != XLLP_DMAC_DCSR_STOP_INTR ) |
| 270 | ROW_DELAY(DEFAULT_TIMEOUT); |
| 271 | |
| 272 | SPI_WaitSSPComplete(); |
| 273 | |
| 274 | Deassert_CS(); |
| 275 | |
| 276 | SPI_DisableSSP(); |
| 277 | |
| 278 | //clear out DMA settings |
| 279 | XllpDmacUnMapDeviceToChannel(spi_tx_dma, SSP_TX_CHANNEL); |
| 280 | |
| 281 | free(convert_buff); |
| 282 | return NoError; |
| 283 | |
| 284 | } |
| 285 | |
| 286 | UINT_T SPINOR_Extend_Write(UINT_T Address, UINT_T Buffer, UINT_T Size) |
| 287 | { |
| 288 | UINT_T Retval = NoError, i, total_size, write_size, status; |
| 289 | UINT_T *buff = (UINT_T *) Buffer; |
| 290 | UINT8_T status1; |
| 291 | |
| 292 | if(Size & 0x3) //make size 4bytes-align |
| 293 | Size = (Size+4)&(~3); |
| 294 | |
| 295 | total_size = Size >> 2; |
| 296 | |
| 297 | if ((Address + Size) > 0x2000000) |
| 298 | return FlashAddrOutOfRange; |
| 299 | |
| 300 | do { |
| 301 | //make sure the device is ready to be written to |
| 302 | SPINOR_ReadStatus(TRUE); |
| 303 | //get device ready to Program |
| 304 | SPINOR_WriteEnable(); |
| 305 | SPINOR_ReadStatus(TRUE); |
| 306 | |
| 307 | write_size = Size > WRITE_SIZE ? WRITE_SIZE : Size; |
| 308 | |
| 309 | //write a byte |
| 310 | if (write_size == WRITE_SIZE) |
| 311 | { |
| 312 | Retval = Extend_Write(Address, Buffer, WRITE_SIZE); |
| 313 | |
| 314 | //update counters |
| 315 | Address+=WRITE_SIZE; |
| 316 | Buffer+=WRITE_SIZE; |
| 317 | Size-=WRITE_SIZE; |
| 318 | } |
| 319 | else |
| 320 | { |
| 321 | Retval = Extend_Write(Address, Buffer, WRITE_SIZE); |
| 322 | Size=0; |
| 323 | } |
| 324 | |
| 325 | SPINOR_ReadStatus(TRUE); |
| 326 | } while( (Size > 0) && (Retval == NoError) ); |
| 327 | |
| 328 | return Retval; |
| 329 | } |
| 330 | |
| 331 | UINT_T Extend_EraseSector(UINT_T secAddr, UINT_T cmdSel) |
| 332 | { |
| 333 | UINT_T Retval = NoError, CMDSelect; |
| 334 | unsigned char cmd[5], data[5]; |
| 335 | |
| 336 | P_SPINOR_T spinor_info = getSPINor_Info(); |
| 337 | |
| 338 | switch (cmdSel) |
| 339 | { |
| 340 | case 0: |
| 341 | //obm_printf("4KB erase command 0x21\n\r"); |
| 342 | CMDSelect = 0x21; |
| 343 | break; |
| 344 | |
| 345 | case 1: |
| 346 | //obm_printf("32KB erase command 0xdc\n\r"); |
| 347 | CMDSelect = 0xdc; |
| 348 | break; |
| 349 | |
| 350 | default: |
| 351 | //obm_printf("64KB erase command 0xdc\n\r"); |
| 352 | CMDSelect = 0xdc; |
| 353 | break; |
| 354 | } |
| 355 | |
| 356 | SPINOR_ReadStatus(TRUE); |
| 357 | SPINOR_WriteEnable(); |
| 358 | SPINOR_ReadStatus(TRUE); |
| 359 | |
| 360 | if (Spansion_SPINOR_Flash) |
| 361 | cmd[0] = CMDSelect; |
| 362 | else |
| 363 | cmd[0] = spinor_info->erase_4bytes_cmd; |
| 364 | |
| 365 | cmd[1] = (secAddr >> 24) & 0xFF; |
| 366 | cmd[2] = (secAddr >> 16) & 0xFF; |
| 367 | cmd[3] = (secAddr >> 8) & 0xFF; |
| 368 | cmd[4] = (secAddr >> 0) & 0xFF; |
| 369 | |
| 370 | SPI_DisableSSP(); |
| 371 | |
| 372 | // workaround for 52MHz SPI bit shift |
| 373 | if (ssp_52mhz) |
| 374 | reg_bit_set(SSP_CR0, SSP_SSCR0_52MM); |
| 375 | //fire it up |
| 376 | reg_bit_set(SSP_CR0, SSP_CR0_SSE); |
| 377 | |
| 378 | Assert_CS(); |
| 379 | |
| 380 | SPI_Write_Read(cmd, data, sizeof(cmd)); |
| 381 | |
| 382 | SPI_WaitSSPComplete(); |
| 383 | |
| 384 | Deassert_CS(); |
| 385 | |
| 386 | //make sure SSP is disabled |
| 387 | SPI_DisableSSP(); |
| 388 | |
| 389 | return Retval; |
| 390 | } |
| 391 | |
| 392 | |
| 393 | UINT_T SPINOR_Extend_Erase(UINT_T Address, UINT_T Size) |
| 394 | { |
| 395 | UINT_T numSectors, i, sector_size, Retval = NoError, zero_address = 0; |
| 396 | |
| 397 | P_FlashProperties_T pFlashP = GetFlashProperties(BOOT_FLASH); |
| 398 | |
| 399 | if ((Address + Size) > 0x2000000) |
| 400 | return FlashAddrOutOfRange; |
| 401 | |
| 402 | if ((Spansion_SPINOR_Flash) && (Address == 0)) |
| 403 | zero_address = 1; |
| 404 | |
| 405 | if (zero_address) |
| 406 | { |
| 407 | for (i = 0; i < 8; i++) |
| 408 | { |
| 409 | Extend_EraseSector(Address, 0); |
| 410 | Address += 0x1000; |
| 411 | } |
| 412 | |
| 413 | Extend_EraseSector(Address, 1); |
| 414 | Address += 0x8000; |
| 415 | } |
| 416 | |
| 417 | sector_size = pFlashP->BlockSize; |
| 418 | |
| 419 | if (Size % pFlashP->BlockSize == 0) |
| 420 | numSectors = Size / pFlashP->BlockSize; |
| 421 | else |
| 422 | numSectors = Size / pFlashP->BlockSize + 1; |
| 423 | |
| 424 | if (zero_address) |
| 425 | numSectors -= 1; |
| 426 | |
| 427 | for (i = 0; i < numSectors; i++) |
| 428 | { |
| 429 | Retval = Extend_EraseSector(Address, 2); |
| 430 | |
| 431 | Address += sector_size; |
| 432 | |
| 433 | if (Retval != NoError) |
| 434 | break; |
| 435 | } |
| 436 | |
| 437 | return Retval; |
| 438 | } |
| 439 | |