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