blob: 8e9775523840650e6cb414d019ef795940f881aa [file] [log] [blame]
Lee Leahyeef40eb2017-03-23 10:54:57 -07001/*
2 * Copyright 2008, Freescale Semiconductor, Inc
3 * Andy Fleming
4 *
5 * Copyright 2013 Google Inc. All rights reserved.
6 * Copyright 2017 Intel Corporation
7 *
8 * MultiMediaCard (MMC), eMMC and Secure Digital (SD) erase support code.
9 * This code is controller independent.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 */
21
Lee Leahyeef40eb2017-03-23 10:54:57 -070022#include "sd_mmc.h"
23#include "storage.h"
24
25uint64_t storage_block_erase(struct storage_media *media, uint64_t start,
26 uint64_t count)
27{
28 struct mmc_command cmd;
29 struct sd_mmc_ctrlr *ctrlr = media->ctrlr;
30
31 if (storage_block_setup(media, start, count, 0) == 0)
32 return 0;
33
34 cmd.cmdidx = MMC_CMD_ERASE_GROUP_START;
35 cmd.resp_type = CARD_RSP_R1;
36 cmd.cmdarg = start;
37 cmd.flags = 0;
38
39 if (ctrlr->send_cmd(ctrlr, &cmd, NULL))
40 return 0;
41
42 cmd.cmdidx = MMC_CMD_ERASE_GROUP_END;
43 cmd.cmdarg = start + count - 1;
44 cmd.resp_type = CARD_RSP_R1;
45 cmd.flags = 0;
46
47 if (ctrlr->send_cmd(ctrlr, &cmd, NULL))
48 return 0;
49
50 cmd.cmdidx = MMC_CMD_ERASE;
51 cmd.cmdarg = MMC_TRIM_ARG; /* just unmap blocks */
52 cmd.resp_type = CARD_RSP_R1;
53 cmd.flags = 0;
54
55 if (ctrlr->send_cmd(ctrlr, &cmd, NULL))
56 return 0;
57
58 size_t erase_blocks;
59 /*
60 * Timeout for TRIM operation on one erase group is defined as:
61 * TRIM timeout = 300ms x TRIM_MULT
62 *
63 * This timeout is expressed in units of 100us to sd_mmc_send_status.
64 *
65 * Hence, timeout_per_erase_block = TRIM timeout * 1000us/100us;
66 */
67 size_t timeout_per_erase_block = (media->trim_mult * 300) * 10;
68 int err = 0;
69
70 erase_blocks = ALIGN_UP(count, media->erase_blocks)
71 / media->erase_blocks;
72
73 while (erase_blocks) {
74 /*
75 * To avoid overflow of timeout value, loop in calls to
76 * sd_mmc_send_status for erase_blocks number of times.
77 */
78 err = sd_mmc_send_status(media, timeout_per_erase_block);
79
80 /* Send status successful, erase action complete. */
81 if (err == 0)
82 break;
83
84 erase_blocks--;
85 }
86
87 /* Total timeout done. Still status not successful. */
88 if (err) {
89 sd_mmc_error("TRIM operation not successful within timeout.\n");
90 return 0;
91 }
92
93 return count;
94}