]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
Merge branch 'u-boot-samsung/master' into 'u-boot-arm/master'
authorAlbert ARIBAUD <albert.u.boot@aribaud.net>
Wed, 19 Jun 2013 10:53:59 +0000 (12:53 +0200)
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>
Wed, 19 Jun 2013 10:53:59 +0000 (12:53 +0200)
Conflicts:
spl/Makefile

1  2 
drivers/mmc/mmc.c
include/mmc.h
spl/Makefile

diff --combined drivers/mmc/mmc.c
index 0a2f5358e2fe386a322a151fdb93cbd5ea50f497,9c0652d9abcf9683d2d5dcc168b482a70bacc562..a492bbb41f5faef7b0d6369de605a8bc5d163d91
@@@ -524,70 -524,48 +524,70 @@@ static int sd_send_op_cond(struct mmc *
        return 0;
  }
  
 -static int mmc_send_op_cond(struct mmc *mmc)
 +/* We pass in the cmd since otherwise the init seems to fail */
 +static int mmc_send_op_cond_iter(struct mmc *mmc, struct mmc_cmd *cmd,
 +              int use_arg)
  {
 -      int timeout = 10000;
 -      struct mmc_cmd cmd;
        int err;
  
 +      cmd->cmdidx = MMC_CMD_SEND_OP_COND;
 +      cmd->resp_type = MMC_RSP_R3;
 +      cmd->cmdarg = 0;
 +      if (use_arg && !mmc_host_is_spi(mmc)) {
 +              cmd->cmdarg =
 +                      (mmc->voltages &
 +                      (mmc->op_cond_response & OCR_VOLTAGE_MASK)) |
 +                      (mmc->op_cond_response & OCR_ACCESS_MODE);
 +
 +              if (mmc->host_caps & MMC_MODE_HC)
 +                      cmd->cmdarg |= OCR_HCS;
 +      }
 +      err = mmc_send_cmd(mmc, cmd, NULL);
 +      if (err)
 +              return err;
 +      mmc->op_cond_response = cmd->response[0];
 +      return 0;
 +}
 +
 +int mmc_send_op_cond(struct mmc *mmc)
 +{
 +      struct mmc_cmd cmd;
 +      int err, i;
 +
        /* Some cards seem to need this */
        mmc_go_idle(mmc);
  
        /* Asking to the card its capabilities */
 -      cmd.cmdidx = MMC_CMD_SEND_OP_COND;
 -      cmd.resp_type = MMC_RSP_R3;
 -      cmd.cmdarg = 0;
 -
 -      err = mmc_send_cmd(mmc, &cmd, NULL);
 +      mmc->op_cond_pending = 1;
 +      for (i = 0; i < 2; i++) {
 +              err = mmc_send_op_cond_iter(mmc, &cmd, i != 0);
 +              if (err)
 +                      return err;
  
 -      if (err)
 -              return err;
 +              /* exit if not busy (flag seems to be inverted) */
 +              if (mmc->op_cond_response & OCR_BUSY)
 +                      return 0;
 +      }
 +      return IN_PROGRESS;
 +}
  
 -      udelay(1000);
 +int mmc_complete_op_cond(struct mmc *mmc)
 +{
 +      struct mmc_cmd cmd;
 +      int timeout = 1000;
 +      uint start;
 +      int err;
  
 +      mmc->op_cond_pending = 0;
 +      start = get_timer(0);
        do {
 -              cmd.cmdidx = MMC_CMD_SEND_OP_COND;
 -              cmd.resp_type = MMC_RSP_R3;
 -              cmd.cmdarg = (mmc_host_is_spi(mmc) ? 0 :
 -                              (mmc->voltages &
 -                              (cmd.response[0] & OCR_VOLTAGE_MASK)) |
 -                              (cmd.response[0] & OCR_ACCESS_MODE));
 -
 -              if (mmc->host_caps & MMC_MODE_HC)
 -                      cmd.cmdarg |= OCR_HCS;
 -
 -              err = mmc_send_cmd(mmc, &cmd, NULL);
 -
 +              err = mmc_send_op_cond_iter(mmc, &cmd, 1);
                if (err)
                        return err;
 -
 -              udelay(1000);
 -      } while (!(cmd.response[0] & OCR_BUSY) && timeout--);
 -
 -      if (timeout <= 0)
 -              return UNUSABLE_ERR;
 +              if (get_timer(start) > timeout)
 +                      return UNUSABLE_ERR;
 +              udelay(100);
 +      } while (!(mmc->op_cond_response & OCR_BUSY));
  
        if (mmc_host_is_spi(mmc)) { /* read OCR for spi */
                cmd.cmdidx = MMC_CMD_SPI_READ_OCR;
@@@ -1296,7 -1274,7 +1296,7 @@@ block_dev_desc_t *mmc_get_dev(int dev
  }
  #endif
  
 -int mmc_init(struct mmc *mmc)
 +int mmc_start_init(struct mmc *mmc)
  {
        int err;
  
        if (err == TIMEOUT) {
                err = mmc_send_op_cond(mmc);
  
 -              if (err) {
 +              if (err && err != IN_PROGRESS) {
                        printf("Card did not respond to voltage select!\n");
                        return UNUSABLE_ERR;
                }
        }
  
 -      err = mmc_startup(mmc);
 +      if (err == IN_PROGRESS)
 +              mmc->init_in_progress = 1;
 +
 +      return err;
 +}
 +
 +static int mmc_complete_init(struct mmc *mmc)
 +{
 +      int err = 0;
 +
 +      if (mmc->op_cond_pending)
 +              err = mmc_complete_op_cond(mmc);
 +
 +      if (!err)
 +              err = mmc_startup(mmc);
        if (err)
                mmc->has_init = 0;
        else
                mmc->has_init = 1;
 +      mmc->init_in_progress = 0;
 +      return err;
 +}
 +
 +int mmc_init(struct mmc *mmc)
 +{
 +      int err = IN_PROGRESS;
 +      unsigned start = get_timer(0);
 +
 +      if (mmc->has_init)
 +              return 0;
 +      if (!mmc->init_in_progress)
 +              err = mmc_start_init(mmc);
 +
 +      if (!err || err == IN_PROGRESS)
 +              err = mmc_complete_init(mmc);
 +      debug("%s: %d, time %lu\n", __func__, err, get_timer(start));
        return err;
  }
  
@@@ -1415,25 -1362,6 +1415,25 @@@ int get_mmc_num(void
        return cur_dev_num;
  }
  
 +void mmc_set_preinit(struct mmc *mmc, int preinit)
 +{
 +      mmc->preinit = preinit;
 +}
 +
 +static void do_preinit(void)
 +{
 +      struct mmc *m;
 +      struct list_head *entry;
 +
 +      list_for_each(entry, &mmc_devices) {
 +              m = list_entry(entry, struct mmc, link);
 +
 +              if (m->preinit)
 +                      mmc_start_init(m);
 +      }
 +}
 +
 +
  int mmc_initialize(bd_t *bis)
  {
        INIT_LIST_HEAD (&mmc_devices);
  
        print_mmc_devices(',');
  
 +      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
diff --combined include/mmc.h
index 566db59ac9fdd5e682f5866b34673164e49e8d15,21d0937d5c92b6b57020636db0057371906314f2..f88f672f111fee172e655167b0284e5b7521774d
@@@ -68,7 -68,6 +68,7 @@@
  #define UNUSABLE_ERR          -17 /* Unusable Card */
  #define COMM_ERR              -18 /* Communications Error */
  #define TIMEOUT                       -19
 +#define IN_PROGRESS           -20 /* operation is in progress */
  
  #define MMC_CMD_GO_IDLE_STATE         0
  #define MMC_CMD_SEND_OP_COND          1
  #define MMC_CMD_APP_CMD                       55
  #define MMC_CMD_SPI_READ_OCR          58
  #define MMC_CMD_SPI_CRC_ON_OFF                59
+ #define MMC_CMD_RES_MAN                       62
+ #define MMC_CMD62_ARG1                        0xefac62ec
+ #define MMC_CMD62_ARG2                        0xcbaea7
  
  #define SD_CMD_SEND_RELATIVE_ADDR     3
  #define SD_CMD_SWITCH_FUNC            6
   */
  #define EXT_CSD_PARTITIONING_SUPPORT  160     /* RO */
  #define EXT_CSD_ERASE_GROUP_DEF               175     /* R/W */
+ #define EXT_CSD_BOOT_BUS_WIDTH                177
  #define EXT_CSD_PART_CONF             179     /* R/W */
  #define EXT_CSD_BUS_WIDTH             183     /* R/W */
  #define EXT_CSD_HS_TIMING             185     /* R/W */
  #define EXT_CSD_BUS_WIDTH_4   1       /* Card is in 4 bit mode */
  #define EXT_CSD_BUS_WIDTH_8   2       /* Card is in 8 bit mode */
  
+ #define EXT_CSD_BOOT_ACK_ENABLE                       (1 << 6)
+ #define EXT_CSD_BOOT_PARTITION_ENABLE         (1 << 3)
+ #define EXT_CSD_PARTITION_ACCESS_ENABLE               (1 << 0)
+ #define EXT_CSD_PARTITION_ACCESS_DISABLE      (0 << 0)
+ #define EXT_CSD_BOOT_ACK(x)           (x << 6)
+ #define EXT_CSD_BOOT_PART_NUM(x)      (x << 3)
+ #define EXT_CSD_PARTITION_ACCESS(x)   (x << 0)
  #define R1_ILLEGAL_COMMAND            (1 << 22)
  #define R1_APP_CMD                    (1 << 5)
  
  /* Maximum block size for MMC */
  #define MMC_MAX_BLOCK_LEN     512
  
+ /* The number of MMC physical partitions.  These consist of:
+  * boot partitions (2), general purpose partitions (4) in MMC v4.4.
+  */
+ #define MMC_NUM_BOOT_PARTITION        2
  struct mmc_cid {
        unsigned long psn;
        unsigned short oid;
@@@ -271,10 -291,6 +292,10 @@@ struct mmc 
        int (*getcd)(struct mmc *mmc);
        int (*getwp)(struct mmc *mmc);
        uint b_max;
 +      char op_cond_pending;   /* 1 if we are waiting on an op_cond command */
 +      char init_in_progress;  /* 1 if we have done mmc_start_init() */
 +      char preinit;           /* start init as early as possible */
 +      uint op_cond_response;  /* the response byte from the last op_cond */
  };
  
  int mmc_register(struct mmc *mmc);
@@@ -291,32 -307,12 +312,37 @@@ int mmc_switch_part(int dev_num, unsign
  int mmc_getcd(struct mmc *mmc);
  int mmc_getwp(struct mmc *mmc);
  void spl_mmc_load(void) __noreturn;
+ /* Function to change the size of boot partition and rpmb partitions */
+ int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
+                                       unsigned long rpmbsize);
+ /* Function to send commands to open/close the specified boot partition */
+ int mmc_boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access);
  
 +/**
 + * Start device initialization and return immediately; it does not block on
 + * polling OCR (operation condition register) status.  Then you should call
 + * mmc_init, which would block on polling OCR status and complete the device
 + * initializatin.
 + *
 + * @param mmc Pointer to a MMC device struct
 + * @return 0 on success, IN_PROGRESS on waiting for OCR status, <0 on error.
 + */
 +int mmc_start_init(struct mmc *mmc);
 +
 +/**
 + * Set preinit flag of mmc device.
 + *
 + * This will cause the device to be pre-inited during mmc_initialize(),
 + * which may save boot time if the device is not accessed until later.
 + * Some eMMC devices take 200-300ms to init, but unfortunately they
 + * must be sent a series of commands to even get them to start preparing
 + * for operation.
 + *
 + * @param mmc         Pointer to a MMC device struct
 + * @param preinit     preinit flag value
 + */
 +void mmc_set_preinit(struct mmc *mmc, int preinit);
 +
  #ifdef CONFIG_GENERIC_MMC
  #define mmc_host_is_spi(mmc)  ((mmc)->host_caps & MMC_MODE_SPI)
  struct mmc *mmc_spi_init(uint bus, uint cs, uint speed, uint mode);
diff --combined spl/Makefile
index d8fe948ff0a77ac3c10083fccd3a6133a6c03c6e,09752bf3467b501e399997976b37f5488d24d0ae..01873de2b16d393e82938ad4c422e206e04b958a
@@@ -88,7 -88,7 +88,7 @@@ ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP34X
  LIBS-y += $(CPUDIR)/omap-common/libomap-common.o
  endif
  
 -ifneq (,$(filter $(SOC), mx25 mx27 mx5 mx6 mx31 mx35))
 +ifneq (,$(CONFIG_MX23)$(filter $(SOC), mx25 mx27 mx5 mx6 mx31 mx35))
  LIBS-y += arch/$(ARCH)/imx-common/libimx-common.o
  endif
  
@@@ -98,6 -98,14 +98,14 @@@ LIBS-y += arch/$(ARCH)/cpu/tegra-common
  LIBS-y += $(CPUDIR)/tegra-common/libtegra-common.o
  endif
  
+ ifneq ($(CONFIG_MX23)$(CONFIG_MX35),)
+ LIBS-y += arch/$(ARCH)/imx-common/libimx-common.o
+ endif
+ ifeq ($(SOC),exynos)
+ LIBS-y += $(CPUDIR)/s5p-common/libs5p-common.o
+ endif
  # Add GCC lib
  ifeq ("$(USE_PRIVATE_LIBGCC)", "yes")
  PLATFORM_LIBGCC = $(SPLTREE)/arch/$(ARCH)/lib/libgcc.o