[U-Boot] [PATCH 25/25] mmc: Add hardware partition support

Simon Glass
2018-11-06T22:21:42Z

MMC devices support multiple partitions, defined by the hardware. At
present U-Boot can only access partition zero. Add support for selecting
other partitions.

Also add a way to check if a partition is write-protected.
Signed-off-by: Simon Glass <sjg@chromium.org>
---

drivers/mmc/mmc.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
include/mmc.h | 31 +++++++++++++++++++++++++++++++
2 files changed, 77 insertions(+)

diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index d6b9cdc9922..5b542524338 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1128,6 +1128,52 @@ int mmc_hwpart_config(struct mmc *mmc,

return 0;
}
+
+int mmc_hwpart_access(struct mmc *mmc, int part)
+{
+ int err;
+ struct mmc_cmd cmd;
+
+ cmd.cmdidx = MMC_CMD_SWITCH;
+ cmd.resp_type = MMC_RSP_R1b;
+
+ /* Clear partition access bits */
+ cmd.cmdarg = (MMC_SWITCH_MODE_CLEAR_BITS << 24) |
+ (EXT_CSD_PART_CONF << 16) |
+ (EXT_CSD_PARTITION_ACCESS(0x7) << 8);
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ debug("Failed to clear partition access bits\n");
+ return err;
+ }
+
+ /* Set partition access bits */
+ cmd.cmdarg = (MMC_SWITCH_MODE_SET_BITS << 24) |
+ (EXT_CSD_PART_CONF << 16) |
+ (EXT_CSD_PARTITION_ACCESS(part) << 8);
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ debug("Failed to change partition\n");
+ return err;
+ }
+
+ return 0;
+}
+
+int mmc_get_boot_wp(struct mmc *mmc)
+{
+ ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN);
+ int err;
+
+ err = mmc_send_ext_csd(mmc, ext_csd);
+ if (err)
+ return err;
+
+ return ext_csd[EXT_CSD_BOOT_WP] & (EXT_CSD_BOOT_WP_PWR_WP_EN
+ | EXT_CSD_BOOT_WP_PERM_WP_EN);
+}
#endif

#if !CONFIG_IS_ENABLED(DM_MMC)
diff --git a/include/mmc.h b/include/mmc.h
index 95548e94c4d..1d0f978f8af 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -215,6 +215,7 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
#define EXT_CSD_WR_REL_PARAM 166 /* R */
#define EXT_CSD_WR_REL_SET 167 /* R/W */
#define EXT_CSD_RPMB_MULT 168 /* RO */
+#define EXT_CSD_BOOT_WP 173 /* R/W */
#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */
#define EXT_CSD_BOOT_BUS_WIDTH 177
#define EXT_CSD_PART_CONF 179 /* R/W */
@@ -279,6 +280,15 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
#define EXT_CSD_EXTRACT_BOOT_PART(x) (((x) >> 3) & 0x7)
#define EXT_CSD_EXTRACT_PARTITION_ACCESS(x) ((x) & 0x7)

+/* Enable boot power-on write protect */
+#define EXT_CSD_BOOT_WP_PWR_WP_EN BIT(0)
+/* Enable boot permanent write protect */
+#define EXT_CSD_BOOT_WP_PERM_WP_EN BIT(2)
+/* Disable use of boot power-on write protect */
+#define EXT_CSD_BOOT_WP_PWR_WP_DIS BIT(6)
+/* Bit 1 (Power-on) or Bit 3 (Permanent) selects the partition to protect */
+#define EXT_CSD_BOOT_WP_PART_SELECT BIT(7)
+
#define EXT_CSD_BOOT_BUS_WIDTH_MODE(x) (x << 3)
#define EXT_CSD_BOOT_BUS_WIDTH_RESET(x) (x << 2)
#define EXT_CSD_BOOT_BUS_WIDTH_WIDTH(x) (x)
@@ -735,6 +745,27 @@ int mmc_switch_part(struct mmc *mmc, unsigned int part_num);
int mmc_hwpart_config(struct mmc *mmc, const struct mmc_hwpart_conf *conf,
enum mmc_hwpart_conf_mode mode);

+/**
+ * Get boot partition write protect status
+ *
+ * @param mmc MMC to get status of
+ * @return 0 if WP is not asserted, non-zero if WP is asserted
+ */
+int mmc_get_boot_wp(struct mmc *mmc);
+
+/**
+ * Change MMC Partition
+ *
+ * Switch access to partition specified in part. Unlike mmc_boot_part_access,
+ * this function will not affect the configured boot partition or boot ack
+ * settings.
+ *
+ * @param mmc MMC to configure
+ * @param part Partition to access (one of PARTITION_ACCESS from spec)
+ * #return 0 on success, -ve on error
+ */
+int mmc_hwpart_access(struct mmc *mmc, int part);
+
#if !CONFIG_IS_ENABLED(DM_MMC)
int mmc_getcd(struct mmc *mmc);
int board_mmc_getcd(struct mmc *mmc);
--
2.19.1.930.g4563a0d9d0-goog