@@ -549,6 +549,147 @@ rt_uint32_t mmcsd_select_voltage(struct rt_mmcsd_host *host, rt_uint32_t ocr)
549549 return ocr ;
550550}
551551
552+ static const rt_uint8_t tuning_blk_pattern_4bit [] =
553+ {
554+ 0xff , 0x0f , 0xff , 0x00 , 0xff , 0xcc , 0xc3 , 0xcc ,
555+ 0xc3 , 0x3c , 0xcc , 0xff , 0xfe , 0xff , 0xfe , 0xef ,
556+ 0xff , 0xdf , 0xff , 0xdd , 0xff , 0xfb , 0xff , 0xfb ,
557+ 0xbf , 0xff , 0x7f , 0xff , 0x77 , 0xf7 , 0xbd , 0xef ,
558+ 0xff , 0xf0 , 0xff , 0xf0 , 0x0f , 0xfc , 0xcc , 0x3c ,
559+ 0xcc , 0x33 , 0xcc , 0xcf , 0xff , 0xef , 0xff , 0xee ,
560+ 0xff , 0xfd , 0xff , 0xfd , 0xdf , 0xff , 0xbf , 0xff ,
561+ 0xbb , 0xff , 0xf7 , 0xff , 0xf7 , 0x7f , 0x7b , 0xde ,
562+ };
563+
564+ static const rt_uint8_t tuning_blk_pattern_8bit [] =
565+ {
566+ 0xff , 0xff , 0x00 , 0xff , 0xff , 0xff , 0x00 , 0x00 ,
567+ 0xff , 0xff , 0xcc , 0xcc , 0xcc , 0x33 , 0xcc , 0xcc ,
568+ 0xcc , 0x33 , 0x33 , 0xcc , 0xcc , 0xcc , 0xff , 0xff ,
569+ 0xff , 0xee , 0xff , 0xff , 0xff , 0xee , 0xee , 0xff ,
570+ 0xff , 0xff , 0xdd , 0xff , 0xff , 0xff , 0xdd , 0xdd ,
571+ 0xff , 0xff , 0xff , 0xbb , 0xff , 0xff , 0xff , 0xbb ,
572+ 0xbb , 0xff , 0xff , 0xff , 0x77 , 0xff , 0xff , 0xff ,
573+ 0x77 , 0x77 , 0xff , 0x77 , 0xbb , 0xdd , 0xee , 0xff ,
574+ 0xff , 0xff , 0xff , 0x00 , 0xff , 0xff , 0xff , 0x00 ,
575+ 0x00 , 0xff , 0xff , 0xcc , 0xcc , 0xcc , 0x33 , 0xcc ,
576+ 0xcc , 0xcc , 0x33 , 0x33 , 0xcc , 0xcc , 0xcc , 0xff ,
577+ 0xff , 0xff , 0xee , 0xff , 0xff , 0xff , 0xee , 0xee ,
578+ 0xff , 0xff , 0xff , 0xdd , 0xff , 0xff , 0xff , 0xdd ,
579+ 0xdd , 0xff , 0xff , 0xff , 0xbb , 0xff , 0xff , 0xff ,
580+ 0xbb , 0xbb , 0xff , 0xff , 0xff , 0x77 , 0xff , 0xff ,
581+ 0xff , 0x77 , 0x77 , 0xff , 0x77 , 0xbb , 0xdd , 0xee ,
582+ };
583+
584+ rt_err_t mmcsd_send_tuning (struct rt_mmcsd_host * host , rt_uint32_t opcode , rt_err_t * cmd_error )
585+ {
586+ rt_err_t err = RT_EOK ;
587+ int size ;
588+ rt_uint8_t * data_buf ;
589+ const rt_uint8_t * tuning_block_pattern ;
590+ struct rt_mmcsd_req req = {};
591+ struct rt_mmcsd_cmd cmd = {};
592+ struct rt_mmcsd_data data = {};
593+ struct rt_mmcsd_io_cfg * io_cfg = & host -> io_cfg ;
594+
595+ if (io_cfg -> bus_width == MMCSD_BUS_WIDTH_8 )
596+ {
597+ tuning_block_pattern = tuning_blk_pattern_8bit ;
598+ size = sizeof (tuning_blk_pattern_8bit );
599+ }
600+ else if (io_cfg -> bus_width == MMCSD_BUS_WIDTH_4 )
601+ {
602+ tuning_block_pattern = tuning_blk_pattern_4bit ;
603+ size = sizeof (tuning_blk_pattern_4bit );
604+ }
605+ else
606+ {
607+ return - RT_EINVAL ;
608+ }
609+
610+ data_buf = rt_malloc (size );
611+ if (!data_buf )
612+ {
613+ return - RT_ENOMEM ;
614+ }
615+
616+ rt_memset (data_buf , 0 , size );
617+ rt_memset (& req , 0 , sizeof (struct rt_mmcsd_req ));
618+ rt_memset (& cmd , 0 , sizeof (struct rt_mmcsd_cmd ));
619+ rt_memset (& data , 0 , sizeof (struct rt_mmcsd_data ));
620+
621+ req .cmd = & cmd ;
622+ req .data = & data ;
623+
624+ cmd .cmd_code = opcode ;
625+ cmd .flags = RESP_R1 | CMD_ADTC ;
626+
627+ data .blksize = size ;
628+ data .blks = 1 ;
629+ data .flags = DATA_DIR_READ ;
630+
631+ /*
632+ * According to the tuning specs, Tuning process
633+ * is normally shorter 40 executions of CMD19,
634+ * and timeout value should be shorter than 150 ms
635+ */
636+ data .timeout_ns = 150 * 1000000 ;
637+
638+ mmcsd_send_request (host , & req );
639+
640+ if (cmd_error )
641+ {
642+ * cmd_error = cmd .err ;
643+ }
644+
645+ if (cmd .err )
646+ {
647+ err = cmd .err ;
648+ goto out_free ;
649+ }
650+
651+ if (data .err )
652+ {
653+ err = data .err ;
654+ goto out_free ;
655+ }
656+
657+ if (rt_memcmp (data_buf , tuning_block_pattern , size ))
658+ {
659+ err = - RT_EIO ;
660+ }
661+
662+ out_free :
663+ rt_free (data_buf );
664+
665+ return err ;
666+ }
667+
668+ rt_err_t mmcsd_send_abort_tuning (struct rt_mmcsd_host * host , rt_uint32_t opcode )
669+ {
670+ struct rt_mmcsd_cmd cmd = {};
671+
672+ /*
673+ * eMMC specification specifies that CMD12 can be used to stop a tuning
674+ * command, but SD specification does not, so do nothing unless it is eMMC.
675+ */
676+ if (opcode != SEND_TUNING_BLOCK_HS200 )
677+ {
678+ return 0 ;
679+ }
680+
681+ cmd .cmd_code = STOP_TRANSMISSION ;
682+ cmd .flags = RESP_SPI_R1 | RESP_R1 | CMD_AC ;
683+
684+ /*
685+ * For drivers that override R1 to R1b, set an arbitrary timeout based
686+ * on the tuning timeout i.e. 150ms.
687+ */
688+ cmd .busy_timeout = 150 ;
689+
690+ return mmcsd_send_cmd (host , & cmd , 0 );
691+ }
692+
552693static void mmcsd_power_up (struct rt_mmcsd_host * host )
553694{
554695 int bit = __rt_fls (host -> valid_ocr ) - 1 ;
0 commit comments