···677677 if (start + count > host->cardinfo.numblocks)
678678 goto out;
679679680680+ int max_nr_blocks = MAX(host->config.max_nr_blocks, 1);
680681 while (count > 0)
681682 {
682682- /* TODO: multiple block transfers */
683683- int xfer_count = 1;
683683+ int xfer_count = count;
684684+ if (xfer_count > max_nr_blocks)
685685+ xfer_count = max_nr_blocks;
684686685687 /* Set block length for non-HCS cards */
686688 if (!host->is_hcs_card)
···692694693695 struct sdmmc_host_command cmd = {
694696 .buffer = buf,
695695- .nr_blocks = 1,
697697+ .nr_blocks = xfer_count,
696698 .block_len = SD_BLOCK_SIZE,
697699 .flags = SDMMC_RESP_SHORT | data_dir,
698700 };
699701700700- if (data_dir == SDMMC_DATA_WRITE)
701701- cmd.command = SD_WRITE_BLOCK;
702702+ if (xfer_count > 1)
703703+ {
704704+ if (data_dir == SDMMC_DATA_WRITE)
705705+ cmd.command = SD_WRITE_MULTIPLE_BLOCK;
706706+ else
707707+ cmd.command = SD_READ_MULTIPLE_BLOCK;
708708+ }
702709 else
703703- cmd.command = SD_READ_SINGLE_BLOCK;
710710+ {
711711+ if (data_dir == SDMMC_DATA_WRITE)
712712+ cmd.command = SD_WRITE_BLOCK;
713713+ else
714714+ cmd.command = SD_READ_SINGLE_BLOCK;
715715+ }
704716705717 if (host->cardinfo.sd2plus)
706718 cmd.argument = start;
···710722 rc = sdmmc_host_submit_cmd(host, &cmd, NULL);
711723 if (rc)
712724 goto out;
725725+726726+ /*
727727+ * NOTE: some controllers can send CMD12 automatically after
728728+ * the end of a transfer, eg. X1000; it might be worth
729729+ * supporting that via a feature flag.
730730+ */
731731+ if (xfer_count > 1)
732732+ {
733733+ memset(&cmd, 0, sizeof(cmd));
734734+ cmd.command = SD_STOP_TRANSMISSION;
735735+ cmd.flags = SDMMC_RESP_SHORT | SDMMC_RESP_BUSY;
736736+737737+ rc = sdmmc_host_submit_cmd(host, &cmd, NULL);
738738+ if (rc)
739739+ goto out;
740740+ }
713741714742 buf += xfer_count * SD_BLOCK_SIZE;
715743 start += xfer_count;
+3
firmware/export/sdmmc_host.h
···207207 uint32_t bus_widths;
208208 uint32_t bus_clocks;
209209210210+ /* Max number of blocks in a multiblock transfer */
211211+ int max_nr_blocks;
212212+210213 /* Set to true if the device is removable at runtime */
211214 bool is_removable;
212215};