diff options
author | Gwendal Grignou <gwendal@chromium.org> | 2014-10-16 14:27:16 -0400 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2014-11-10 06:40:36 -0500 |
commit | 0f762426769a517d5b278e4e5d579fcea6801734 (patch) | |
tree | 8d3377adab4f8360e559f9b090f2fa32967a61c4 | |
parent | e7791079ae89d91024019e11a1f430d38c491246 (diff) |
mmc: core: Report firmware version for eMMC 5.0 devices.
For eMMC 5.0 compliant device, firmware version is stored in ext_csd.
Report firmware as a 64bit hexa decimal. Vendor can use hexa or ascii
string to report firmware version.
Also add FFU related EXT_CSD register and note if the device is FFU capable.
Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r-- | drivers/mmc/core/mmc.c | 27 | ||||
-rw-r--r-- | include/linux/mmc/card.h | 3 | ||||
-rw-r--r-- | include/linux/mmc/mmc.h | 3 |
3 files changed, 32 insertions, 1 deletions
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index bcde451f6d91..a5e05ceb554c 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -628,6 +628,14 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) | |||
628 | card->ext_csd.data_sector_size = 512; | 628 | card->ext_csd.data_sector_size = 512; |
629 | } | 629 | } |
630 | 630 | ||
631 | /* eMMC v5 or later */ | ||
632 | if (card->ext_csd.rev >= 7) { | ||
633 | memcpy(card->ext_csd.fwrev, &ext_csd[EXT_CSD_FIRMWARE_VERSION], | ||
634 | MMC_FIRMWARE_LEN); | ||
635 | card->ext_csd.ffu_capable = | ||
636 | (ext_csd[EXT_CSD_SUPPORTED_MODE] & 0x1) && | ||
637 | !(ext_csd[EXT_CSD_FW_CONFIG] & 0x1); | ||
638 | } | ||
631 | out: | 639 | out: |
632 | return err; | 640 | return err; |
633 | } | 641 | } |
@@ -722,7 +730,7 @@ MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1], | |||
722 | MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); | 730 | MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year); |
723 | MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9); | 731 | MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9); |
724 | MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9); | 732 | MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9); |
725 | MMC_DEV_ATTR(fwrev, "0x%x\n", card->cid.fwrev); | 733 | MMC_DEV_ATTR(ffu_capable, "%d\n", card->ext_csd.ffu_capable); |
726 | MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); | 734 | MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev); |
727 | MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); | 735 | MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid); |
728 | MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name); | 736 | MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name); |
@@ -735,6 +743,22 @@ MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size); | |||
735 | MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult); | 743 | MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult); |
736 | MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors); | 744 | MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors); |
737 | 745 | ||
746 | static ssize_t mmc_fwrev_show(struct device *dev, | ||
747 | struct device_attribute *attr, | ||
748 | char *buf) | ||
749 | { | ||
750 | struct mmc_card *card = mmc_dev_to_card(dev); | ||
751 | |||
752 | if (card->ext_csd.rev < 7) { | ||
753 | return sprintf(buf, "0x%x\n", card->cid.fwrev); | ||
754 | } else { | ||
755 | return sprintf(buf, "0x%*phN\n", MMC_FIRMWARE_LEN, | ||
756 | card->ext_csd.fwrev); | ||
757 | } | ||
758 | } | ||
759 | |||
760 | static DEVICE_ATTR(fwrev, S_IRUGO, mmc_fwrev_show, NULL); | ||
761 | |||
738 | static struct attribute *mmc_std_attrs[] = { | 762 | static struct attribute *mmc_std_attrs[] = { |
739 | &dev_attr_cid.attr, | 763 | &dev_attr_cid.attr, |
740 | &dev_attr_csd.attr, | 764 | &dev_attr_csd.attr, |
@@ -742,6 +766,7 @@ static struct attribute *mmc_std_attrs[] = { | |||
742 | &dev_attr_erase_size.attr, | 766 | &dev_attr_erase_size.attr, |
743 | &dev_attr_preferred_erase_size.attr, | 767 | &dev_attr_preferred_erase_size.attr, |
744 | &dev_attr_fwrev.attr, | 768 | &dev_attr_fwrev.attr, |
769 | &dev_attr_ffu_capable.attr, | ||
745 | &dev_attr_hwrev.attr, | 770 | &dev_attr_hwrev.attr, |
746 | &dev_attr_manfid.attr, | 771 | &dev_attr_manfid.attr, |
747 | &dev_attr_name.attr, | 772 | &dev_attr_name.attr, |
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 0ba8f251f8ef..4d69c00497bd 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
@@ -88,6 +88,9 @@ struct mmc_ext_csd { | |||
88 | unsigned int data_tag_unit_size; /* DATA TAG UNIT size */ | 88 | unsigned int data_tag_unit_size; /* DATA TAG UNIT size */ |
89 | unsigned int boot_ro_lock; /* ro lock support */ | 89 | unsigned int boot_ro_lock; /* ro lock support */ |
90 | bool boot_ro_lockable; | 90 | bool boot_ro_lockable; |
91 | bool ffu_capable; /* Firmware upgrade support */ | ||
92 | #define MMC_FIRMWARE_LEN 8 | ||
93 | u8 fwrev[MMC_FIRMWARE_LEN]; /* FW version */ | ||
91 | u8 raw_exception_status; /* 54 */ | 94 | u8 raw_exception_status; /* 54 */ |
92 | u8 raw_partition_support; /* 160 */ | 95 | u8 raw_partition_support; /* 160 */ |
93 | u8 raw_rpmb_size_mult; /* 168 */ | 96 | u8 raw_rpmb_size_mult; /* 168 */ |
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index 1cd00b3a75b9..49ad7a943638 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h | |||
@@ -296,6 +296,7 @@ struct _mmc_csd { | |||
296 | #define EXT_CSD_SANITIZE_START 165 /* W */ | 296 | #define EXT_CSD_SANITIZE_START 165 /* W */ |
297 | #define EXT_CSD_WR_REL_PARAM 166 /* RO */ | 297 | #define EXT_CSD_WR_REL_PARAM 166 /* RO */ |
298 | #define EXT_CSD_RPMB_MULT 168 /* RO */ | 298 | #define EXT_CSD_RPMB_MULT 168 /* RO */ |
299 | #define EXT_CSD_FW_CONFIG 169 /* R/W */ | ||
299 | #define EXT_CSD_BOOT_WP 173 /* R/W */ | 300 | #define EXT_CSD_BOOT_WP 173 /* R/W */ |
300 | #define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */ | 301 | #define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */ |
301 | #define EXT_CSD_PART_CONFIG 179 /* R/W */ | 302 | #define EXT_CSD_PART_CONFIG 179 /* R/W */ |
@@ -332,6 +333,8 @@ struct _mmc_csd { | |||
332 | #define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */ | 333 | #define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */ |
333 | #define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */ | 334 | #define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */ |
334 | #define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */ | 335 | #define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */ |
336 | #define EXT_CSD_FIRMWARE_VERSION 254 /* RO, 8 bytes */ | ||
337 | #define EXT_CSD_SUPPORTED_MODE 493 /* RO */ | ||
335 | #define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */ | 338 | #define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */ |
336 | #define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */ | 339 | #define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */ |
337 | #define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */ | 340 | #define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */ |