]> git.sur5r.net Git - u-boot/blobdiff - drivers/mmc/mmc.c
Merge branch 'u-boot-samsung/master' into 'u-boot-arm/master'
[u-boot] / drivers / mmc / mmc.c
index e6a296a5762c939736d47aed83529f113c983635..55026759ede4d41cbb26e2096a965e87e9b812b6 100644 (file)
@@ -4,23 +4,7 @@
  *
  * Based vaguely on the Linux code
  *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <config.h>
@@ -254,7 +238,7 @@ err_out:
 }
 
 static unsigned long
-mmc_berase(int dev_num, unsigned long start, lbaint_t blkcnt)
+mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
 {
        int err = 0;
        struct mmc *mmc = find_mmc_device(dev_num);
@@ -266,7 +250,8 @@ mmc_berase(int dev_num, unsigned long start, lbaint_t blkcnt)
 
        if ((start % mmc->erase_grp_size) || (blkcnt % mmc->erase_grp_size))
                printf("\n\nCaution! Your devices Erase group is 0x%x\n"
-                       "The erase range would be change to 0x%lx~0x%lx\n\n",
+                      "The erase range would be change to "
+                      "0x" LBAF "~0x" LBAF "\n\n",
                       mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
                       ((start + blkcnt + mmc->erase_grp_size)
                       & ~(mmc->erase_grp_size - 1)) - 1);
@@ -289,14 +274,14 @@ mmc_berase(int dev_num, unsigned long start, lbaint_t blkcnt)
 }
 
 static ulong
-mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
+mmc_write_blocks(struct mmc *mmc, lbaint_t start, lbaint_t blkcnt, const void*src)
 {
        struct mmc_cmd cmd;
        struct mmc_data data;
        int timeout = 1000;
 
        if ((start + blkcnt) > mmc->block_dev.lba) {
-               printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
+               printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
                        start + blkcnt, mmc->block_dev.lba);
                return 0;
        }
@@ -346,7 +331,7 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
 }
 
 static ulong
-mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
+mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void*src)
 {
        lbaint_t cur, blocks_todo = blkcnt;
 
@@ -369,7 +354,7 @@ mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
        return blkcnt;
 }
 
-static int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start,
+static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
                           lbaint_t blkcnt)
 {
        struct mmc_cmd cmd;
@@ -408,7 +393,7 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start,
        return blkcnt;
 }
 
-static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
+static ulong mmc_bread(int dev_num, lbaint_t start, lbaint_t blkcnt, void *dst)
 {
        lbaint_t cur, blocks_todo = blkcnt;
 
@@ -420,7 +405,7 @@ static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
                return 0;
 
        if ((start + blkcnt) > mmc->block_dev.lba) {
-               printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
+               printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
                        start + blkcnt, mmc->block_dev.lba);
                return 0;
        }
@@ -1498,8 +1483,144 @@ int mmc_initialize(bd_t *bis)
        if (board_mmc_init(bis) < 0)
                cpu_mmc_init(bis);
 
+#ifndef CONFIG_SPL_BUILD
        print_mmc_devices(',');
+#endif
 
        do_preinit();
        return 0;
 }
+
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+/*
+ * 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)
+{
+       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) {
+               debug("mmc_boot_partition_size_change: Error1 = %d\n", err);
+               return err;
+       }
+
+       /* 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) {
+               debug("mmc_boot_partition_size_change: Error2 = %d\n", err);
+               return err;
+       }
+       /* 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) {
+               debug("mmc_boot_partition_size_change: Error3 = %d\n", err);
+               return err;
+       }
+       /* 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) {
+               debug("mmc_boot_partition_size_change: Error4 = %d\n", err);
+               return err;
+       }
+       return 0;
+}
+
+/*
+ * This function shall form and send the commands to open / close the
+ * boot partition specified by user.
+ *
+ * Input Parameters:
+ * ack: 0x0 - No boot acknowledge sent (default)
+ *     0x1 - Boot acknowledge sent during boot operation
+ * part_num: User selects boot data that will be sent to master
+ *     0x0 - Device not boot enabled (default)
+ *     0x1 - Boot partition 1 enabled for boot
+ *     0x2 - Boot partition 2 enabled for boot
+ * access: User selects partitions to access
+ *     0x0 : No access to boot partition (default)
+ *     0x1 : R/W boot partition 1
+ *     0x2 : R/W boot partition 2
+ *     0x3 : R/W Replay Protected Memory Block (RPMB)
+ *
+ * Returns 0 on success.
+ */
+int mmc_boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
+{
+       int err;
+       struct mmc_cmd cmd;
+
+       /* Boot ack enable, boot partition enable , boot partition access */
+       cmd.cmdidx = MMC_CMD_SWITCH;
+       cmd.resp_type = MMC_RSP_R1b;
+
+       cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+                       (EXT_CSD_PART_CONF << 16) |
+                       ((EXT_CSD_BOOT_ACK(ack) |
+                       EXT_CSD_BOOT_PART_NUM(part_num) |
+                       EXT_CSD_PARTITION_ACCESS(access)) << 8);
+
+       err = mmc_send_cmd(mmc, &cmd, NULL);
+       if (err) {
+               if (access) {
+                       debug("mmc boot partition#%d open fail:Error1 = %d\n",
+                             part_num, err);
+               } else {
+                       debug("mmc boot partition#%d close fail:Error = %d\n",
+                             part_num, err);
+               }
+               return err;
+       }
+
+       if (access) {
+               /* 4bit transfer mode at booting time. */
+               cmd.cmdidx = MMC_CMD_SWITCH;
+               cmd.resp_type = MMC_RSP_R1b;
+
+               cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+                               (EXT_CSD_BOOT_BUS_WIDTH << 16) |
+                               ((1 << 0) << 8);
+
+               err = mmc_send_cmd(mmc, &cmd, NULL);
+               if (err) {
+                       debug("mmc boot partition#%d open fail:Error2 = %d\n",
+                             part_num, err);
+                       return err;
+               }
+       }
+       return 0;
+}
+#endif