Skip to contentSkip to conversation

mmc: Support FFU for Samsung eMMC v4.5

PATCH In review Seunguk Shin 2 participants 2 messages Apr 4, 2014 – Apr 7, 2014 MMC, SD and SDIO

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 mmc: Support FFU for Samsung eMMC v4.5

This change adds support to field firmware update (ffu) for Samsung emmc v4.5.

Samsung eMMC 4.5 FFU protocol is similar with eMMC 5.0 FFU without MODE_OPERATION.
It uses the different EXT_CSD offset.

This patch depends on patch mmc: Support-FFU-for-eMMC-v5.0 committed by Avi Shchislowski <[email protected]>

---
 drivers/mmc/card/Kconfig |   9 +++++
 drivers/mmc/card/block.c |   8 ++++
 drivers/mmc/card/ffu.c   | 100
+++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mmc/ffu.h  |  14 +++++++
 4 files changed, 131 insertions(+)
drivers/mmc/card/Kconfig +9 -0
index d1ea14f..4b0126d 100644
@@ -76,3 +76,12 @@ config MMC_FFU
 	  This is an option to run firmware update on eMMC 5.0.
 	  Field firmware updates (FFU) enables features enhancement
 	  in the field.
+
+config MMC_FFU_SAMSUNG45
+	bool "FFU SUPPORT for Samsung eMMC 4.5."
+	depends on MMC_FFU
+	default n
+	help
+	  This is an option to run firmware update on Samsung eMMC 4.5.
+	  Field firmware updates (FFU) enables features enhancment
+	  in the field.
drivers/mmc/card/block.c +8 -0
index e50cded..ca8ba57 100644
@@ -536,6 +536,14 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
 		goto cmd_rel_host;
 	}
 
+#ifdef CONFIG_MMC_FFU_SAMSUNG45
+	if (cmd.opcode == MMC_FFU_SAMSUNG45_OP) {
+		err = mmc_ffu_execute(card, &cmd, idata->buf,
+				idata->buf_bytes);
+		goto cmd_rel_host;
+	}
+#endif
+
 	err = mmc_blk_part_switch(card, md);
 	if (err)
 		goto cmd_rel_host;
drivers/mmc/card/ffu.c +100 -0

103 lines not on this page · raw message

include/linux/mmc/ffu.h +14 -0
index 009e98b..abf56e6 100644
@@ -27,6 +27,9 @@
  */
 #define MMC_FFU_DOWNLOAD_OP 302
 #define MMC_FFU_INSTALL_OP 303
+#ifdef CONFIG_MMC_FFU_SAMSUNG45
+#define MMC_FFU_SAMSUNG45_OP 304
+#endif
 
 #define MMC_FFU_MODE_SET 0x1
 #define MMC_FFU_MODE_NORMAL 0x0
@@ -47,6 +50,10 @@
 int mmc_ffu_download(struct mmc_card *card, struct mmc_command *cmd,
 	u8 *data, int buf_bytes);
 int mmc_ffu_install(struct mmc_card *card);
+#ifdef CONFIG_MMC_FFU_SAMSUNG45
+int mmc_ffu_execute(struct mmc_card *card, struct mmc_command *cmd,
+	u8 *data, int buf_bytes);
+#endif
 #else
 static inline int mmc_ffu_download(struct mmc_card *card,
 	struct mmc_command *cmd, u8 *data, int buf_bytes)
@@ -57,6 +64,13 @@ static inline int mmc_ffu_install(struct mmc_card *card)
 {
 	return -ENOSYS;
 }
+#ifdef CONFIG_MMC_FFU_SAMSUNG45
+static inline int mmc_ffu_execute(struct mmc_card *card,
+	struct mmc_command *cmd, u8 *data, int buf_bytes)
+{
+	return -ENOSYS;
+}
+#endif
 
 #endif
 #endif /* FFU_H_ */
Signature · 1 line
1.8.3.2
#1 lore raw
Quoted 2 lines · Seunguk Shin

This change adds support to field firmware update (ffu) for Samsung emmc v4.5.

Wow. I'm amazed and very happy that this has been posted. :)

Quoted 6 lines

Samsung eMMC 4.5 FFU protocol is similar with eMMC 5.0 FFU without MODE_OPERATION.
It uses the different EXT_CSD offset.

This patch depends on patch mmc: Support-FFU-for-eMMC-v5.0 committed by Avi Shchislowski <[email protected]>

While some of the plumbing for loading FW will change, I think most of this patch can be re-used.

Comments below relate to "production use" - not the core FFU implementation.

THANKS! :)
grant

Quoted 16 lines
---
 drivers/mmc/card/Kconfig |   9 +++++
 drivers/mmc/card/block.c |   8 ++++
 drivers/mmc/card/ffu.c   | 100
+++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mmc/ffu.h  |  14 +++++++
 4 files changed, 131 insertions(+)
drivers/mmc/card/Kconfig +0 -0
index d1ea14f..4b0126d 100644
@@ -76,3 +76,12 @@ config MMC_FFU
          This is an option to run firmware update on eMMC 5.0.
          Field firmware updates (FFU) enables features enhancement

drivers/mmc/card/Kconfig config MMC_FFU · line 87

Quoted 10 lines
drivers/mmc/card/Kconfig +9 -0
          in the field.
+
+config MMC_FFU_SAMSUNG45
+       bool "FFU SUPPORT for Samsung eMMC 4.5."
+       depends on MMC_FFU
+       default n
+       help
+         This is an option to run firmware update on Samsung eMMC 4.5.
+         Field firmware updates (FFU) enables features enhancment
+         in the field.

I don't believe FFU needs a separate Kconfig option. FW update is a standard function. The code below has enough protection in it to detect at run time that it won't break something else by accident.

Quoted 49 lines
drivers/mmc/card/block.c +8 -0
index e50cded..ca8ba57 100644
@@ -536,6 +536,14 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
                goto cmd_rel_host;
        }
 
+#ifdef CONFIG_MMC_FFU_SAMSUNG45
+       if (cmd.opcode == MMC_FFU_SAMSUNG45_OP) {
+               err = mmc_ffu_execute(card, &cmd, idata->buf,
+                               idata->buf_bytes);
+               goto cmd_rel_host;
+       }
+#endif
+
        err = mmc_blk_part_switch(card, md);
        if (err)
                goto cmd_rel_host;
drivers/mmc/card/ffu.c +22 -0
index 092a791..a5eed6c 100644
@@ -608,3 +608,103 @@ exit:
 }
 EXPORT_SYMBOL(mmc_ffu_install);
 
+#ifdef CONFIG_MMC_FFU_SAMSUNG45
+
+#define EXT_CSD_MODE_CONFIG_SAMSUNG45  133
+#define EXT_CSD_FFU_STATUS_SAMSUNG45   253
+
+int mmc_ffu_execute(struct mmc_card *card, struct mmc_command *cmd,
+       u8 *data, int buf_bytes)
+{
+       u8 ext_csd[CARD_BLOCK_SIZE];
+       int err;
+       int ret = 0;
+
+       /* Read the EXT_CSD */
+       err = mmc_send_ext_csd(card, ext_csd);
+       if (err) {
+               u32 status;
+               pr_err("FFU: %s: error %d sending ext_csd\n",
+                       mmc_hostname(card->host), err);
+               goto exit;
+       }
+
+       /*

drivers/mmc/card/ffu.c exit: · line 642

Quoted 10 lines
drivers/mmc/card/ffu.c +10 -0
+        * Check Manufacturer ID and revision,
+        * This is only for Samsung eMMC 4.5
+        */
+       if (card->cid.manfid != CID_MANFID_SAMSUNG ||
+           card->ext_csd.rev != 6) {
+               err = -EINVAL;
+               pr_err("FFU: %s: error %d FFU is not supported\n",
+                       mmc_hostname(card->host), err);
+               goto exit;
+       }

This is the "checking for the right HW" that I'm referring to previously.

Quoted 114 lines
drivers/mmc/card/ffu.c +68 -0
+
+       /* Check if FFU is supported by card */
+       if (!FFU_SUPPORTED_MODE(ext_csd[EXT_CSD_SUPPORTED_MODE])) {
+               err = -EINVAL;
+               pr_err("FFU: %s: error %d FFU is not supported\n",
+                       mmc_hostname(card->host), err);
+               goto exit;
+       }
+
+       if (FFU_ENABLED(ext_csd[EXT_CSD_FW_CONFIG])) {
+               err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+                       EXT_CSD_FW_CONFIG, MMC_FFU_ENABLE,
+                       card->ext_csd.generic_cmd6_time);
+               if (err) {
+                       pr_err("%s: switch to FFU failed with error %d\n",
+                               mmc_hostname(card->host), err);
+                       return err;
+               }
+       }
+
+       /* set device to FFU mode */
+       err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+               EXT_CSD_MODE_CONFIG_SAMSUNG45, MMC_FFU_MODE_SET,
+               card->ext_csd.generic_cmd6_time);
+       if (err) {
+               pr_err("FFU: %s: error %d FFU is not supported\n",
+                       mmc_hostname(card->host), err);
+               goto exit;
+       }
+       cmd->arg = 0xc7810000;
+
+       err = mmc_ffu_write(card, data, cmd->arg, buf_bytes);
+
+       /* host switch back to work in normal MMC Read/Write commands */
+       ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+               EXT_CSD_MODE_CONFIG_SAMSUNG45, MMC_FFU_MODE_NORMAL,
+               card->ext_csd.generic_cmd6_time);
+       if (ret)
+               err = ret;
+
+       /* read ext_csd */
+       err = mmc_send_ext_csd(card, ext_csd);
+       if (err) {
+               pr_err("FFU: %s: error %d sending ext_csd\n",
+               mmc_hostname(card->host), err);
+               goto exit;
+       }
+
+       /* return status */
+       err = ext_csd[EXT_CSD_FFU_STATUS_SAMSUNG45];
+       if (!err) {
+               pr_err("FFU: %s: error %d FFU execute:\n",
+                       mmc_hostname(card->host), err);
+               err = -EINVAL;
+               goto exit;
+       }
+       err = mmc_ffu_restart(card);
+       if (err) {
+               pr_err("FFU: %s: error %d FFU execute:\n",
+                       mmc_hostname(card->host), err);
+       }
+exit:
+       return err;
+}
+EXPORT_SYMBOL(mmc_ffu_execute);
+
+#endif
+
include/linux/mmc/ffu.h +14 -1
index 009e98b..abf56e6 100644
@@ -27,6 +27,9 @@
  */
 #define MMC_FFU_DOWNLOAD_OP 302
 #define MMC_FFU_INSTALL_OP 303
+#ifdef CONFIG_MMC_FFU_SAMSUNG45
+#define MMC_FFU_SAMSUNG45_OP 304
+#endif
 
 #define MMC_FFU_MODE_SET 0x1
 #define MMC_FFU_MODE_NORMAL 0x0
@@ -47,6 +50,10 @@
 int mmc_ffu_download(struct mmc_card *card, struct mmc_command *cmd,
        u8 *data, int buf_bytes);
 int mmc_ffu_install(struct mmc_card *card);
+#ifdef CONFIG_MMC_FFU_SAMSUNG45
+int mmc_ffu_execute(struct mmc_card *card, struct mmc_command *cmd,
+       u8 *data, int buf_bytes);
+#endif
 #else
 static inline int mmc_ffu_download(struct mmc_card *card,
        struct mmc_command *cmd, u8 *data, int buf_bytes)
@@ -57,6 +64,13 @@ static inline int mmc_ffu_install(struct mmc_card *card)
 {
        return -ENOSYS;
 }
+#ifdef CONFIG_MMC_FFU_SAMSUNG45
+static inline int mmc_ffu_execute(struct mmc_card *card,
+       struct mmc_command *cmd, u8 *data, int buf_bytes)
+{
+       return -ENOSYS;
+}
+#endif
 
 #endif
 #endif /* FFU_H_ */
--

1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html