1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2016 Google, Inc 4 * Written by Amar <amarendra.xt@samsung.com> 5 */ 6 7 #include <common.h> 8 #include <mmc.h> 9 #include "mmc_private.h" 10 11 /* 12 * This function changes the size of boot partition and the size of rpmb 13 * partition present on EMMC devices. 14 * 15 * Input Parameters: 16 * struct *mmc: pointer for the mmc device strcuture 17 * bootsize: size of boot partition 18 * rpmbsize: size of rpmb partition 19 * 20 * Returns 0 on success. 21 */ 22 23 int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, 24 unsigned long rpmbsize) 25 { 26 int err; 27 struct mmc_cmd cmd; 28 29 /* Only use this command for raw EMMC moviNAND. Enter backdoor mode */ 30 cmd.cmdidx = MMC_CMD_RES_MAN; 31 cmd.resp_type = MMC_RSP_R1b; 32 cmd.cmdarg = MMC_CMD62_ARG1; 33 34 err = mmc_send_cmd(mmc, &cmd, NULL); 35 if (err) { 36 debug("mmc_boot_partition_size_change: Error1 = %d\n", err); 37 return err; 38 } 39 40 /* Boot partition changing mode */ 41 cmd.cmdidx = MMC_CMD_RES_MAN; 42 cmd.resp_type = MMC_RSP_R1b; 43 cmd.cmdarg = MMC_CMD62_ARG2; 44 45 err = mmc_send_cmd(mmc, &cmd, NULL); 46 if (err) { 47 debug("mmc_boot_partition_size_change: Error2 = %d\n", err); 48 return err; 49 } 50 /* boot partition size is multiple of 128KB */ 51 bootsize = (bootsize * 1024) / 128; 52 53 /* Arg: boot partition size */ 54 cmd.cmdidx = MMC_CMD_RES_MAN; 55 cmd.resp_type = MMC_RSP_R1b; 56 cmd.cmdarg = bootsize; 57 58 err = mmc_send_cmd(mmc, &cmd, NULL); 59 if (err) { 60 debug("mmc_boot_partition_size_change: Error3 = %d\n", err); 61 return err; 62 } 63 /* RPMB partition size is multiple of 128KB */ 64 rpmbsize = (rpmbsize * 1024) / 128; 65 /* Arg: RPMB partition size */ 66 cmd.cmdidx = MMC_CMD_RES_MAN; 67 cmd.resp_type = MMC_RSP_R1b; 68 cmd.cmdarg = rpmbsize; 69 70 err = mmc_send_cmd(mmc, &cmd, NULL); 71 if (err) { 72 debug("mmc_boot_partition_size_change: Error4 = %d\n", err); 73 return err; 74 } 75 return 0; 76 } 77 78 /* 79 * Modify EXT_CSD[177] which is BOOT_BUS_WIDTH 80 * based on the passed in values for BOOT_BUS_WIDTH, RESET_BOOT_BUS_WIDTH 81 * and BOOT_MODE. 82 * 83 * Returns 0 on success. 84 */ 85 int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode) 86 { 87 return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_BUS_WIDTH, 88 EXT_CSD_BOOT_BUS_WIDTH_MODE(mode) | 89 EXT_CSD_BOOT_BUS_WIDTH_RESET(reset) | 90 EXT_CSD_BOOT_BUS_WIDTH_WIDTH(width)); 91 } 92 93 /* 94 * Modify EXT_CSD[179] which is PARTITION_CONFIG (formerly BOOT_CONFIG) 95 * based on the passed in values for BOOT_ACK, BOOT_PARTITION_ENABLE and 96 * PARTITION_ACCESS. 97 * 98 * Returns 0 on success. 99 */ 100 int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access) 101 { 102 int ret; 103 u8 part_conf; 104 105 part_conf = EXT_CSD_BOOT_ACK(ack) | 106 EXT_CSD_BOOT_PART_NUM(part_num) | 107 EXT_CSD_PARTITION_ACCESS(access); 108 109 ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF, 110 part_conf); 111 if (!ret) 112 mmc->part_config = part_conf; 113 114 return ret; 115 } 116 117 /* 118 * Modify EXT_CSD[162] which is RST_n_FUNCTION based on the given value 119 * for enable. Note that this is a write-once field for non-zero values. 120 * 121 * Returns 0 on success. 122 */ 123 int mmc_set_rst_n_function(struct mmc *mmc, u8 enable) 124 { 125 return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_RST_N_FUNCTION, 126 enable); 127 } 128