xref: /aosp_15_r20/external/coreboot/src/commonlib/storage/storage_erase.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * MultiMediaCard (MMC), eMMC and Secure Digital (SD) erase support code.
4  * This code is controller independent.
5  */
6 
7 #include "sd_mmc.h"
8 #include "storage.h"
9 
storage_block_erase(struct storage_media * media,uint64_t start,uint64_t count)10 uint64_t storage_block_erase(struct storage_media *media, uint64_t start,
11 	uint64_t count)
12 {
13 	struct mmc_command cmd;
14 	struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
15 
16 	if (storage_block_setup(media, start, count, 0) == 0)
17 		return 0;
18 
19 	cmd.cmdidx = MMC_CMD_ERASE_GROUP_START;
20 	cmd.resp_type = CARD_RSP_R1;
21 	cmd.cmdarg = start;
22 	cmd.flags = 0;
23 
24 	if (ctrlr->send_cmd(ctrlr, &cmd, NULL))
25 		return 0;
26 
27 	cmd.cmdidx = MMC_CMD_ERASE_GROUP_END;
28 	cmd.cmdarg = start + count - 1;
29 	cmd.resp_type = CARD_RSP_R1;
30 	cmd.flags = 0;
31 
32 	if (ctrlr->send_cmd(ctrlr, &cmd, NULL))
33 		return 0;
34 
35 	cmd.cmdidx = MMC_CMD_ERASE;
36 	cmd.cmdarg = MMC_TRIM_ARG;	/* just unmap blocks */
37 	cmd.resp_type = CARD_RSP_R1;
38 	cmd.flags = 0;
39 
40 	if (ctrlr->send_cmd(ctrlr, &cmd, NULL))
41 		return 0;
42 
43 	size_t erase_blocks;
44 	/*
45 	 * Timeout for TRIM operation on one erase group is defined as:
46 	 * TRIM timeout = 300ms x TRIM_MULT
47 	 *
48 	 * This timeout is expressed in units of 100us to sd_mmc_send_status.
49 	 *
50 	 * Hence, timeout_per_erase_block = TRIM timeout * 1000us/100us;
51 	 */
52 	size_t timeout_per_erase_block = (media->trim_mult * 300) * 10;
53 	int err = 0;
54 
55 	erase_blocks = ALIGN_UP(count, media->erase_blocks)
56 		/ media->erase_blocks;
57 
58 	while (erase_blocks) {
59 		/*
60 		 * To avoid overflow of timeout value, loop in calls to
61 		 * sd_mmc_send_status for erase_blocks number of times.
62 		 */
63 		err = sd_mmc_send_status(media, timeout_per_erase_block);
64 
65 		/* Send status successful, erase action complete. */
66 		if (err == 0)
67 			break;
68 
69 		erase_blocks--;
70 	}
71 
72 	/* Total timeout done. Still status not successful. */
73 	if (err) {
74 		sd_mmc_error("TRIM operation not successful within timeout.\n");
75 		return 0;
76 	}
77 
78 	return count;
79 }
80