blob: 986e6c500b1516914f8e5dda491f8d5d59c7cab9 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass84f9df92016-06-12 23:30:18 -06002/*
3 * Copyright (C) 2016 Google, Inc
4 * Written by Amar <amarendra.xt@samsung.com>
Simon Glass84f9df92016-06-12 23:30:18 -06005 */
6
Simon Glass0f2af882020-05-10 11:40:05 -06007#include <log.h>
Simon Glass84f9df92016-06-12 23:30:18 -06008#include <mmc.h>
9#include "mmc_private.h"
10
Luke Wang0cd63572025-03-25 16:29:14 +080011static int mmc_resize_boot_micron(struct mmc *mmc, unsigned long bootsize,
12 unsigned long rpmbsize)
13{
14 int err;
Simon Glass84f9df92016-06-12 23:30:18 -060015
Luke Wang0cd63572025-03-25 16:29:14 +080016 /* Micron eMMC doesn't support resizing RPMB partition */
17 (void)rpmbsize;
18
19 /* BOOT partition size is multiple of 128KB */
20 bootsize = (bootsize * 1024) / 128;
21
22 if (bootsize > 0xff)
23 bootsize = 0xff;
24
25 /* Set EXT_CSD[175] ERASE_GROUP_DEF to 0x01 */
26 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
27 EXT_CSD_ERASE_GROUP_DEF, 0x01);
28 if (err)
29 goto error;
30
31 /* Set EXT_CSD[127:125] for BOOT partition size, [125] is low byte */
32 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
33 EXT_CSD_BOOT_SIZE_MULT_MICRON, bootsize);
34 if (err)
35 goto error;
36
37 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
38 EXT_CSD_BOOT_SIZE_MULT_MICRON + 1, 0x00);
39 if (err)
40 goto error;
41
42 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
43 EXT_CSD_BOOT_SIZE_MULT_MICRON + 2, 0x00);
44 if (err)
45 goto error;
46
47 /* Set EXT_CSD[155] PARTITION_SETTING_COMPLETE to 0x01 */
48 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
49 EXT_CSD_PARTITION_SETTING, 0x01);
50 if (err)
51 goto error;
52
53 return 0;
54
55error:
56 debug("%s: Error = %d\n", __func__, err);
57 return err;
58}
59
60static int mmc_resize_boot_sandisk(struct mmc *mmc, unsigned long bootsize,
61 unsigned long rpmbsize)
62{
63 int err;
64 struct mmc_cmd cmd;
65
66 /* BOOT/RPMB partition size is multiple of 128KB */
67 bootsize = (bootsize * 1024) / 128;
68 rpmbsize = (rpmbsize * 1024) / 128;
69
70 if (bootsize > 0xff)
71 bootsize = 0xff;
72
73 if (rpmbsize > 0xff)
74 rpmbsize = 0xff;
75
76 /* Send BOOT/RPMB resize op code */
77 cmd.cmdidx = MMC_CMD_RES_MAN;
78 cmd.resp_type = MMC_RSP_R1b;
79 cmd.cmdarg = MMC_CMD62_ARG_SANDISK;
80
81 err = mmc_send_cmd(mmc, &cmd, NULL);
82 if (err)
83 goto error;
84
85 /* Arg: BOOT partition size */
86 cmd.cmdidx = MMC_CMD_RES_MAN;
87 cmd.resp_type = MMC_RSP_R1b;
88 cmd.cmdarg = bootsize;
89
90 err = mmc_send_cmd(mmc, &cmd, NULL);
91 if (err)
92 goto error;
93
94 /* Arg: RPMB partition size */
95 cmd.cmdidx = MMC_CMD_RES_MAN;
96 cmd.resp_type = MMC_RSP_R1b;
97 cmd.cmdarg = rpmbsize;
98
99 err = mmc_send_cmd(mmc, &cmd, NULL);
100 if (err)
101 goto error;
102
103 return 0;
104
105error:
106 debug("%s: Error = %d\n", __func__, err);
107 return err;
108}
109
110static int mmc_resize_boot_samsung(struct mmc *mmc, unsigned long bootsize,
111 unsigned long rpmbsize)
Simon Glass84f9df92016-06-12 23:30:18 -0600112{
113 int err;
114 struct mmc_cmd cmd;
115
116 /* Only use this command for raw EMMC moviNAND. Enter backdoor mode */
117 cmd.cmdidx = MMC_CMD_RES_MAN;
118 cmd.resp_type = MMC_RSP_R1b;
119 cmd.cmdarg = MMC_CMD62_ARG1;
120
121 err = mmc_send_cmd(mmc, &cmd, NULL);
Luke Wang0cd63572025-03-25 16:29:14 +0800122 if (err)
123 goto error;
Simon Glass84f9df92016-06-12 23:30:18 -0600124
125 /* Boot partition changing mode */
126 cmd.cmdidx = MMC_CMD_RES_MAN;
127 cmd.resp_type = MMC_RSP_R1b;
128 cmd.cmdarg = MMC_CMD62_ARG2;
129
130 err = mmc_send_cmd(mmc, &cmd, NULL);
Luke Wang0cd63572025-03-25 16:29:14 +0800131 if (err)
132 goto error;
133
Simon Glass84f9df92016-06-12 23:30:18 -0600134 /* boot partition size is multiple of 128KB */
135 bootsize = (bootsize * 1024) / 128;
136
137 /* Arg: boot partition size */
138 cmd.cmdidx = MMC_CMD_RES_MAN;
139 cmd.resp_type = MMC_RSP_R1b;
140 cmd.cmdarg = bootsize;
141
142 err = mmc_send_cmd(mmc, &cmd, NULL);
Luke Wang0cd63572025-03-25 16:29:14 +0800143 if (err)
144 goto error;
145
Simon Glass84f9df92016-06-12 23:30:18 -0600146 /* RPMB partition size is multiple of 128KB */
147 rpmbsize = (rpmbsize * 1024) / 128;
148 /* Arg: RPMB partition size */
149 cmd.cmdidx = MMC_CMD_RES_MAN;
150 cmd.resp_type = MMC_RSP_R1b;
151 cmd.cmdarg = rpmbsize;
152
153 err = mmc_send_cmd(mmc, &cmd, NULL);
Luke Wang0cd63572025-03-25 16:29:14 +0800154 if (err)
155 goto error;
156
Simon Glass84f9df92016-06-12 23:30:18 -0600157 return 0;
Luke Wang0cd63572025-03-25 16:29:14 +0800158
159error:
160 debug("%s: Error = %d\n", __func__, err);
161 return err;
162}
163
164/*
165 * This function changes the size of BOOT partition and the size of RPMB
166 * partition present on eMMC devices.
167 *
168 * Input Parameters:
169 * struct *mmc: pointer for the mmc device strcuture
170 * bootsize: size of BOOT partition
171 * rpmbsize: size of RPMB partition
172 *
173 * Returns 0 on success.
174 */
175
176int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
177 unsigned long rpmbsize)
178{
179 switch (mmc->cid[0] >> 24) {
180 case CID_MANFID_MICRON:
181 return mmc_resize_boot_micron(mmc, bootsize, rpmbsize);
182 case CID_MANFID_SAMSUNG:
183 return mmc_resize_boot_samsung(mmc, bootsize, rpmbsize);
184 case CID_MANFID_SANDISK:
185 return mmc_resize_boot_sandisk(mmc, bootsize, rpmbsize);
186 default:
187 printf("Unsupported manufacturer id 0x%02x\n",
188 mmc->cid[0] >> 24);
189 return -EPERM;
190 }
Simon Glass84f9df92016-06-12 23:30:18 -0600191}
192
193/*
194 * Modify EXT_CSD[177] which is BOOT_BUS_WIDTH
195 * based on the passed in values for BOOT_BUS_WIDTH, RESET_BOOT_BUS_WIDTH
196 * and BOOT_MODE.
197 *
198 * Returns 0 on success.
199 */
200int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode)
201{
Masahiro Yamadacdb67f32016-09-06 22:17:32 +0900202 return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_BUS_WIDTH,
203 EXT_CSD_BOOT_BUS_WIDTH_MODE(mode) |
204 EXT_CSD_BOOT_BUS_WIDTH_RESET(reset) |
205 EXT_CSD_BOOT_BUS_WIDTH_WIDTH(width));
Simon Glass84f9df92016-06-12 23:30:18 -0600206}
207
208/*
209 * Modify EXT_CSD[179] which is PARTITION_CONFIG (formerly BOOT_CONFIG)
210 * based on the passed in values for BOOT_ACK, BOOT_PARTITION_ENABLE and
211 * PARTITION_ACCESS.
212 *
213 * Returns 0 on success.
214 */
215int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
216{
Angelo Dureghellof54f7532017-08-01 14:27:10 +0200217 int ret;
218 u8 part_conf;
219
220 part_conf = EXT_CSD_BOOT_ACK(ack) |
221 EXT_CSD_BOOT_PART_NUM(part_num) |
222 EXT_CSD_PARTITION_ACCESS(access);
223
224 ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
225 part_conf);
226 if (!ret)
227 mmc->part_config = part_conf;
228
229 return ret;
Simon Glass84f9df92016-06-12 23:30:18 -0600230}
231
232/*
233 * Modify EXT_CSD[162] which is RST_n_FUNCTION based on the given value
234 * for enable. Note that this is a write-once field for non-zero values.
235 *
236 * Returns 0 on success.
237 */
238int mmc_set_rst_n_function(struct mmc *mmc, u8 enable)
239{
240 return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_RST_N_FUNCTION,
241 enable);
242}