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