1 /******************************************************************************* 2 * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions. 3 * 4 * SPDX-License-Identifier: MIT 5 * 6 * PolarFire SoC MSS eMMC SD driver API's for internal use cases. 7 * 8 */ 9 /*=========================================================================*//** 10 Note: The MSS_MMC_pause_sdma_write_hpi(), MSS_MMC_resume_sdma_write_hpi(), 11 MSS_MMC_packed_read(), MSS_MMC_packed_write(), MSS_MMC_cq_single_task_write(), 12 MSS_MMC_cq_single_task_read()functions provided purely for SVG use cases. 13 14 -------------------------------- 15 High Priority Interrupt 16 -------------------------------- 17 The following functions are used for eMMC high priority interrupt operation: 18 - MSS_MMC_pause_sdma_write_hpi() 19 - MSS_MMC_resume_sdma_write_hpi() 20 21 To stop ongoing multiple block write transfers to the eMMC device using the 22 high priority interrupt, a call is made to the MSS_MMC_pause_sdma_write_hpi() 23 function. 24 25 To resume previously interrupted multiple block transfer of eMMC device, 26 a call is made to the MSS_MMC_resume_sdma_write_hpi() function. 27 28 -------------------------------- 29 Packed Commands 30 -------------------------------- 31 The following functions are used for eMMC packed command read and write: 32 - MSS_MMC_packed_read() 33 - MSS_MMC_packed_write() 34 35 To read several multiple blocks of data stored within the eMMC device using 36 the packed group of read commands, a call is made to the MSS_MMC_packed_read() 37 function, specifying the base address of the buffer holding the data of the 38 packed command header block and the base address of buffer where the data 39 read from the eMMC device will be stored. 40 41 To write several multiple blocks of data to the eMMC device using the packed 42 group of write commands, a call is made to the MSS_MMC_packed_write() 43 function, specifying the base address of the buffer holding the data of the 44 packed command header block and the base address of buffer containing the 45 data blocks to be stored into the eMMC device. 46 47 -------------------------------- 48 Command Queue 49 -------------------------------- 50 The following functions are used for eMMC command queue single task operation: 51 - MSS_MMC_cq_single_task_write() 52 - MSS_MMC_cq_single_task_read() 53 54 To write a single block or multiple blocks of data to the eMMC device using 55 a command queue, a call is made to the MSS_MMC_cq_single_task_write() 56 function. This function supports a single task only. 57 58 To read a single block or multiple blocks of data stored within the eMMC 59 device using a command queue, a call is made to the 60 MSS_MMC_cq_single_task_read() function. This function supports a single task 61 only. 62 63 *//*=========================================================================*/ 64 #ifndef __MSS_MMC_INTERNAL_API_H 65 #define __MSS_MMC_INTERNAL_API_H 66 67 #ifdef __cplusplus 68 extern "C" 69 #endif 70 71 /*-------------------------------------------------------------------------*//** 72 The MSS_MMC_pause_sdma_write_hpi() function is used to pause the ongoing SDMA 73 write transfer using the eMMC high priority interrupt (HPI). 74 75 Note: This MSS_MMC_pause_sdma_write_hpi()function has parameters provided 76 purely for svg use case. if this function in production release then we 77 should remove the need for parameters. 78 79 @param src 80 This parameter is a pointer to a buffer containing actual the data to be 81 stored in the eMMC device. The src parameter must be identical to the src 82 parameter of the MSS_MMC_sdma_write() function. 83 84 @param dest 85 This parameter specifies the sector address in the eMMC device where the block 86 is to be stored. The dest parameter must be identical to the dest parameter of 87 the MSS_MMC_sdma_write() function. 88 89 @param size 90 The parameter size specifies the size in bytes of the requested transfer. 91 The size parameter must be identical to the size parameter of the 92 MSS_MMC_sdma_write() function. 93 94 @return 95 This function returns a value of type mss_mmc_status_t which specifies the 96 transfer status of the operation. 97 98 Example: 99 The following example shows how to initialize the device and perform an HPI 100 101 @code 102 103 #define SECT_1 0x01u 104 #define BUFFER_SIZE 4096u 105 106 mss_mmc_cfg_t g_mmc0; 107 mss_mmc_status_t ret_status; 108 uint8_t data_buffer[BUFFER_SIZE]; 109 uint32_t loop_count; 110 111 g_mmc0.clk_rate = MSS_MMC_CLOCK_25MHZ; 112 g_mmc0.card_type = MSS_MMC_CARD_TYPE_MMC; 113 g_mmc0.data_bus_width = MSS_MMC_DATA_WIDTH_4BIT; 114 g_mmc0.bus_speed_mode = MSS_MMC_MODE_LEGACY; 115 g_mmc0.bus_voltage = MSS_MMC_3_3V_BUS_VOLTAGE; 116 117 for (loop_count = 0; loop_count < (BUFFER_SIZE); loop_count++) 118 { 119 data_buffer[loop_count] = 0x45 + loop_count; 120 } 121 122 ret_status = MSS_MMC_init(&g_mmc0); 123 if (MSS_MMC_INIT_SUCCESS == ret_status) 124 { 125 ret_status = MSS_MMC_sdma_write(data_buffer, SECT_1, BUFFER_SIZE); 126 if(ret_status == MSS_MMC_TRANSFER_IN_PROGRESS) 127 { 128 ret_status = MSS_MMC_pause_sdma_write_hpi(data_buffer, SECT_1, 129 BUFFER_SIZE); 130 if(ret_status == MSS_MMC_TRANSFER_SUCCESS) 131 { 132 //.. 133 } 134 } 135 } 136 @endcode 137 */ 138 mss_mmc_status_t 139 MSS_MMC_pause_sdma_write_hpi 140 ( 141 const uint8_t *src, 142 uint32_t dest, 143 uint32_t size 144 ); 145 146 /*-------------------------------------------------------------------------*//** 147 The MSS_MMC_resume_sdma_write_hpi() function is used to resume writing the 148 remaining blocks to the target device which was previously interrupted by 149 a call to MSS_MMC_pause_sdma_write_hpi(). 150 151 @param 152 This function has no parameters. 153 154 @return 155 This function returns a value of type mss_mmc_status_t which specifies the 156 transfer status of the operation. 157 158 Example: 159 The following example shows how to initialize the device and perform a HPI 160 interrupt and resume remaining block operation. 161 162 @code 163 164 #define SECT_1 0x01u 165 #define BUFFER_SIZE 4096u 166 167 mss_mmc_cfg_t g_mmc0; 168 mss_mmc_status_t ret_status; 169 uint8_t data_buffer[BUFFER_SIZE]; 170 uint32_t loop_count; 171 172 g_mmc0.clk_rate = MSS_MMC_CLOCK_25MHZ; 173 g_mmc0.card_type = MSS_MMC_CARD_TYPE_MMC; 174 g_mmc0.data_bus_width = MSS_MMC_DATA_WIDTH_4BIT; 175 g_mmc0.bus_speed_mode = MSS_MMC_MODE_LEGACY; 176 g_mmc0.bus_voltage = MSS_MMC_3_3V_BUS_VOLTAGE; 177 178 for (loop_count = 0; loop_count < (BUFFER_SIZE); loop_count++) 179 { 180 data_buffer[loop_count] = 0x45 + loop_count; 181 } 182 183 ret_status = MSS_MMC_init(&g_mmc0); 184 if (MSS_MMC_INIT_SUCCESS == ret_status) 185 { 186 ret_status = MSS_MMC_sdma_write(data_buffer, SECT_1, BUFFER_SIZE); 187 if(ret_status == MSS_MMC_TRANSFER_IN_PROGRESS) 188 { 189 ret_status = MSS_MMC_pause_sdma_write_hpi(data_buffer, SECT_1, 190 BUFFER_SIZE); 191 if(ret_status == MSS_MMC_TRANSFER_SUCCESS) 192 { 193 ret_status = MSS_MMC_resume_sdma_write_hpi(); 194 if(ret_status == MSS_MMC_TRANSFER_IN_PROGRESS) 195 { 196 do 197 { 198 ret_status = MSS_MMC_get_transfer_status(); 199 }while(ret_status == MSS_MMC_TRANSFER_IN_PROGRESS); 200 } 201 } 202 } 203 } 204 @endcode 205 */ 206 mss_mmc_status_t MSS_MMC_resume_sdma_write_hpi(void); 207 208 /*-------------------------------------------------------------------------*//** 209 The MSS_MMC_packed_write() function is used to transmit a packed group of data 210 from the host to the eMMC device. The write commands can be packed in a group 211 of commands (all write) that transfer the data for all commands in the group 212 in one transfer on the bus. 213 Note : This function is a non-blocking function and returns immediately after 214 initiating the write transfer. 215 216 @param src 217 This parameter is a pointer to a buffer containing the data blocks to be 218 stored in the eMMC device. The first block containing the packed-command 219 header and all data sectors of the individual packed commands are appended 220 together after the header. 221 222 @param dest 223 Specifies the sector address in the eMMC device where the block is to be 224 stored. The dest shall be the same address that is specified by the first 225 individual write command in the packed group. 226 227 @param size 228 Specifies the size in bytes of the requested transfer. The value of size must 229 be a multiple of 512. The size parameter shall be the sum of all block counts 230 of the individual writes plus one for the header. 231 232 @return 233 This function returns a value of type mss_mmc_status_t which specifies the 234 transfer status of the operation. 235 236 Example: 237 This example shows how to initialize the device and perform a packed write 238 transfer. 239 @code 240 241 #define SECT_9 0x09u 242 #define BUFFER_SIZE 4096u 243 244 mss_mmc_cfg_t g_mmc0; 245 mss_mmc_status_t ret_status; 246 uint8_t data_buffer[BUFFER_SIZE]; 247 uint32_t loop_count; 248 uint8_t packed_write[512]; 249 250 g_mmc0.clk_rate = MSS_MMC_CLOCK_25MHZ; 251 g_mmc0.card_type = MSS_MMC_CARD_TYPE_MMC; 252 g_mmc0.data_bus_width = MSS_MMC_DATA_WIDTH_4BIT; 253 g_mmc0.bus_speed_mode = MSS_MMC_MODE_LEGACY; 254 g_mmc0.bus_voltage = MSS_MMC_3_3V_BUS_VOLTAGE; 255 256 packed_write[0] = 0x01; // version 257 packed_write[1] = 0x02; // 0x2 - write 258 packed_write[2] = 0x02; // no of entries 259 packed_write[3] = 0x00; 260 packed_write[4] = 0x00; 261 packed_write[5] = 0x00; 262 packed_write[6] = 0x00; 263 packed_write[7] = 0x00; 264 packed_write[8] = 0x04; // CMD23 arg1 - 4 blocks 265 packed_write[9] = 0x00; 266 packed_write[10] = 0x00; 267 packed_write[11] = 0x00; 268 packed_write[12] = 0x09; // CMD25 arg1 - sector no 9 269 packed_write[13] = 0x00; 270 packed_write[14] = 0x00; 271 packed_write[15] = 0x00; 272 packed_write[16] = 0x04; // CMD23 arg2 - 4-blocks 273 packed_write[17] = 0x00; 274 packed_write[18] = 0x00; 275 packed_write[19] = 0x00; 276 packed_write[20] = 0x29; // CMD25 agr2 - sector no 0x29 277 packed_write[21] = 0x00; 278 packed_write[22] = 0x00; 279 packed_write[23] = 0x00; 280 281 for (loop_count = 24; loop_count < 512; loop_count++) 282 { 283 packed_write[loop_count] = 0; 284 } 285 for (loop_count = 0; loop_count < (BUFFER_SIZE); loop_count++) 286 { 287 data_buffer[loop_count] = 0x45 + loop_count; 288 } 289 // packed header block 290 for (loop_count = 0; loop_count < 512; loop_count++) 291 { 292 data_buffer[loop_count] = packed_write[loop_count]; 293 } 294 resp_reg = MMC_init(&g_mmc0); 295 if (MSS_MMC_INIT_SUCCESS == ret_status) 296 { 297 ret_status = MSS_MMC_packed_write(data_buffer, SECT_9, BUFFER_SIZE); 298 if (ret_status == MSS_MMC_TRANSFER_IN_PROGRESS) 299 { 300 do 301 { 302 ret_status = MSS_MMC_get_transfer_status(); 303 }while (ret_status == MSS_MMC_TRANSFER_IN_PROGRESS) 304 } 305 } 306 @endcode 307 */ 308 mss_mmc_status_t 309 MSS_MMC_packed_write 310 ( 311 const uint8_t *src, 312 uint32_t dest, 313 uint32_t size 314 ); 315 316 /*-------------------------------------------------------------------------*//** 317 The MSS_MMC_packed_read() function is used to read several multiple block of 318 data from the device to the host using packed group. The read commands can be 319 packed in group of commands (all read) that transfer the data for all commands 320 in the group in one transfer on the bus. 321 Note : This function is a non-blocking function and returns immediately after 322 initiating the block transfer. 323 324 @param src 325 Specifies the sector address in the eMMC device where the block is to be read. 326 The src shall be the same address that is specified by the first individual 327 read command in the packed group. 328 329 @param dest 330 This parameter is a pointer to a buffer where the data read from the eMMC 331 device will be stored. The buffer to which this parameter points should be 332 declared with a minimum size of 512 bytes. 333 334 @param packed_header 335 This parameter is a pointer to a buffer containing the packed-command header 336 block. 337 338 @param size 339 Specifies the size in bytes of the requested transfer. The value of size must 340 be a multiple of 512. The size parameter shall be the sum of all block counts 341 of the individual read. 342 343 @return 344 This function returns a value of type mss_mmc_status_t which specifies the 345 transfer status of the operation. 346 347 Example: 348 This example shows how to initialize the device and perform a packed read 349 transfer. 350 351 @code 352 353 #define SECT_9 0x09u 354 #define BUFFER_SIZE 4096u 355 356 mss_mmc_cfg_t g_mmc0; 357 mss_mmc_status_t ret_status; 358 uint8_t data_buffer[BUFFER_SIZE]; 359 uint32_t loop_count; 360 uint8_t packed_read[512]; 361 362 g_mmc0.clk_rate = MSS_MMC_CLOCK_25MHZ; 363 g_mmc0.card_type = MSS_MMC_CARD_TYPE_MMC; 364 g_mmc0.data_bus_width = MSS_MMC_DATA_WIDTH_4BIT; 365 g_mmc0.bus_speed_mode = MSS_MMC_MODE_LEGACY; 366 g_mmc0.bus_voltage = MSS_MMC_3_3V_BUS_VOLTAGE; 367 368 packed_read[0] = 0x01; // version 369 packed_read[1] = 0x02; // 0x1 - read 370 packed_read[2] = 0x02; // no of entries 371 packed_read[3] = 0x00; 372 packed_read[4] = 0x00; 373 packed_read[5] = 0x00; 374 packed_read[6] = 0x00; 375 packed_read[7] = 0x00; 376 packed_read[8] = 0x04; // CMD23 arg1 - 4 blocks 377 packed_read[9] = 0x00; 378 packed_read[10] = 0x00; 379 packed_read[11] = 0x00; 380 packed_read[12] = 0x09; // CMD18 arg1 - sector no 9 381 packed_read[13] = 0x00; 382 packed_read[14] = 0x00; 383 packed_read[15] = 0x00; 384 packed_read[16] = 0x04; // CMD23 arg2 - 4-blocks 385 packed_read[17] = 0x00; 386 packed_read[18] = 0x00; 387 packed_read[19] = 0x00; 388 packed_read[20] = 0x29; // CMD18 agr2 - sector no 0x29 389 packed_read[21] = 0x00; 390 packed_read[22] = 0x00; 391 packed_read[23] = 0x00; 392 for(loop_count = 24; loop_count < 512; loop_count++) 393 { 394 packed_read[loop_count] = 0; 395 } 396 for(loop_count = 0; loop_count < (BUFFER_SIZE); loop_count++) 397 { 398 data_buffer[loop_count] = = 0x00; 399 } 400 resp_reg = MMC_init(&g_mmc0); 401 if (MSS_MMC_INIT_SUCCESS == ret_status) 402 { 403 ret_status = MSS_MMC_packed_read(SECT_9, data_buffer, 404 (uint32 *)packed_read, BUFFER_SIZE); 405 if (ret_status == MSS_MMC_TRANSFER_IN_PROGRESS) 406 { 407 do 408 { 409 ret_status = MSS_MMC_get_transfer_status(); 410 }while (ret_status == MSS_MMC_TRANSFER_IN_PROGRESS) 411 } 412 } 413 414 @endcode 415 */ 416 mss_mmc_status_t 417 MSS_MMC_packed_read 418 ( 419 uint32_t src, 420 uint8_t *dest, 421 uint32_t *packed_header, 422 uint32_t size 423 ); 424 /*-------------------------------------------------------------------------*//** 425 The MSS_MMC_cq_single_task_write() function is used to transmit a single block 426 or multiple blocks of data from the host controller to the eMMC device using 427 command queue with single task based on the data size. The size of the block 428 of data transferred by this function must be set to 512 bytes or a multiple of 429 512 bytes. The 512 bytes is the standard sector size for all eMMC 430 devices with a capacity of greater than 2 GB. 431 432 Note: A call to MSS_MMC_cq_single_task_write() while a transfer is in 433 progress will not initiate a new transfer. Use the MSS_MMC_get_transfer_status() 434 function or a completion handler registered by the MSS_MMC_set_handler() 435 function to check the status of the current transfer before calling the 436 MSS_MMC_cq_single_task_write() function again. 437 438 Note: This function is a non-blocking function and returns immediately after 439 initiating the write transfer. 440 441 Note: This MSS_MMC_cq_single_task_write() and MSS_MMC_cq_single_task_read() 442 functions are provided purely for svg use case. For production release we 443 will remove. 444 445 @param src 446 This parameter is a pointer to a buffer containing the data to be stored 447 in the eMMC device. The buffer to which this parameter points must be 448 declared with a minimum size of 512 bytes. 449 450 @param dest 451 Specifies the sector address in the eMMC device where the data is 452 to be stored. 453 Note: For eMMC devices of greater than 2 GB in size, this address refers to a 454 512 byte sector. 455 456 @param task_id 457 Specifies the eMMC command queue task id number 0 to 31 458 459 @param size 460 Specifies the size in bytes of the requested transfer. The value of size must 461 be a multiple of 512 but not greater than (32MB - 512). 462 463 @return 464 This function returns a value of type mss_mmc_status_t which specifies the 465 transfer status of the operation. 466 467 Example: 468 The following example shows how to initialize the device and perform a multi 469 block transfer.. 470 @code 471 472 #define SECT_1 0x01u 473 #define BUFFER_SIZE 4096u 474 #define TASK_ID 0x01 475 476 mss_mmc_cfg_t g_mmc0; 477 mss_mmc_status_t ret_status; 478 uint8_t data_buffer[BUFFER_SIZE]; 479 uint32_t loop_count; 480 481 g_mmc0.clk_rate = MSS_MMC_CLOCK_25MHZ; 482 g_mmc0.card_type = MSS_MMC_CARD_TYPE_MMC; 483 g_mmc0.data_bus_width = MSS_MMC_DATA_WIDTH_4BIT; 484 g_mmc0.bus_speed_mode = MSS_MMC_MODE_LEGACY; 485 g_mmc0.bus_voltage = MSS_MMC_3_3V_BUS_VOLTAGE; 486 487 for (loop_count = 0; loop_count < (BUFFER_SIZE); loop_count++) 488 { 489 data_buffer[loop_count] = 0x45 + loop_count; 490 } 491 492 ret_status = MSS_MMC_init(&g_mmc0); 493 if (MSS_MMC_INIT_SUCCESS == ret_status) 494 { 495 ret_status = MSS_MMC_cq_init(); 496 if ( MSS_MMC_INIT_SUCCESS == ret_status) 497 { 498 ret_status = MSS_MMC_cq_single_task_write(data_buffer, SECT_1, 499 TASK_ID, BUFFER_SIZE); 500 do 501 { 502 ret_status = MSS_MMC_get_transfer_status(); 503 }while (ret_status == MSS_MMC_TRANSFER_IN_PROGRESS) 504 } 505 } 506 @endcode 507 */ 508 mss_mmc_status_t 509 MSS_MMC_cq_single_task_write 510 ( 511 const uint8_t *src, 512 uint32_t dest, 513 uint8_t task_id, 514 uint32_t size 515 ); 516 /*-------------------------------------------------------------------------*//** 517 The MSS_MMC_cq_single_task_read() function is used to read a single or 518 multiple blocks of data from the eMMC device to the host controller using 519 command queue with single task based on the data size. The size of the block 520 of data read by this function must be set to 512 bytes or a multiple of 521 512 bytes. The 512 bytes is the standard sector size for all eMMC devices 522 with a capacity of greater than 2 GB. 523 524 Note: A call to MSS_MMC_cq_single_task_read() while a transfer is in progress 525 will not initiate a new transfer. Use the MSS_MMC_get_transfer_status() 526 function or a completion handler registered by the MSS_MMC_set_handler() 527 function to check the status of the current transfer before calling the 528 MSS_MMC_cq_single_task_read() function again. 529 530 Note: This function is a non-blocking function and returns immediately after 531 initiating the write transfer. 532 533 @param src 534 Specifies the sector address in the eMMC device from where the data is 535 to be read. 536 Note: For eMMC devices of greater than 2 GB in size, this address refers 537 to a 512-byte sector. 538 539 @param dest 540 This parameter is a pointer to a buffer where the data to read from the eMMC 541 device will be stored. The buffer to which this parameter points must be 542 declared with a minimum size of 512 bytes. 543 544 @param task_id 545 Specifies the eMMC command queue task id number 0 to 31 546 547 @param size 548 Specifies the size in bytes of the requested transfer. The value of size must 549 be a multiple of 512 but not greater than (32MB - 512). 550 551 @return 552 This function returns a value of type mss_mmc_status_t which specifies the 553 transfer status of the operation. 554 555 Example: 556 The following example shows how to initialize the device and perform a multi 557 block transfer. 558 559 @code 560 561 #define SECT_1 0x01u 562 #define BUFFER_SIZE 4096u 563 #define TASK_ID 0x02 564 565 mss_mmc_cfg_t g_mmc0; 566 mss_mmc_status_t ret_status; 567 uint8_t data_buffer[BUFFER_SIZE]; 568 uint32_t loop_count; 569 570 g_mmc0.clk_rate = MSS_MMC_CLOCK_25MHZ; 571 g_mmc0.card_type = MSS_MMC_CARD_TYPE_MMC; 572 g_mmc0.data_bus_width = MSS_MMC_DATA_WIDTH_4BIT; 573 g_mmc0.bus_speed_mode = MSS_MMC_MODE_LEGACY; 574 g_mmc0.bus_voltage = MSS_MMC_3_3V_BUS_VOLTAGE; 575 576 for (loop_count = 0; loop_count < (BUFFER_SIZE); loop_count++) 577 { 578 data_buffer[loop_count] = 0x45 + loop_count; 579 } 580 581 ret_status = MSS_MMC_init(&g_mmc0); 582 if (MSS_MMC_INIT_SUCCESS == ret_status) 583 { 584 ret_status = MSS_MMC_cq_init(); 585 if (MSS_MMC_INIT_SUCCESS == ret_status) 586 { 587 ret_status = MSS_MMC_cq_single_task_read(SECT_1, data_buffer, 588 TASK_ID, BUFFER_SIZE); 589 do 590 { 591 ret_status = MSS_MMC_get_transfer_status(); 592 }while (ret_status == MSS_MMC_TRANSFER_IN_PROGRESS) 593 } 594 } 595 @endcode 596 */ 597 mss_mmc_status_t 598 MSS_MMC_cq_single_task_read 599 ( 600 uint32_t src, 601 uint8_t *dest, 602 uint8_t task_id, 603 uint32_t size 604 ); 605 606 #ifdef __cplusplus 607 } 608 #endif 609 610 #endif /* __MSS_MMC_INTERNAL_API_H */ 611