[linux-yocto] [PATCH 1/1] mmc: sdhci: Preset value not supported in Baytrail eMMC
chong.yi.chai at intel.com
chong.yi.chai at intel.com
Wed Mar 30 20:15:49 PDT 2016
From: "Chai, Chong Yi" <chong.yi.chai at intel.com>
---
features/soc/baytrail/baytrail.scc | 7 +
.../mmc-block-Fix-checkpatch.pl-warning.patch | 31 ++
...mc-block-implement-write-request-blocking.patch | 180 ++++++++++
.../mmc-block-refactor-read-only-handling.patch | 214 ++++++++++++
...orce-BYT-SDCARD-host-to-run-with-SDR25-mo.patch | 80 +++++
...reset-value-not-supported-in-Baytrail-eMM.patch | 47 +++
...dd-DDR50-1.8V-mode-support-for-BayTrail-e.patch | 50 +++
...-whole-device-temporary-write-protection-.patch | 367 +++++++++++++++++++++
8 files changed, 976 insertions(+)
create mode 100644 features/soc/baytrail/mmc-block-Fix-checkpatch.pl-warning.patch
create mode 100644 features/soc/baytrail/mmc-block-implement-write-request-blocking.patch
create mode 100644 features/soc/baytrail/mmc-block-refactor-read-only-handling.patch
create mode 100644 features/soc/baytrail/mmc-sdhci-Force-BYT-SDCARD-host-to-run-with-SDR25-mo.patch
create mode 100644 features/soc/baytrail/mmc-sdhci-Preset-value-not-supported-in-Baytrail-eMM.patch
create mode 100644 features/soc/baytrail/mmc-sdhci-add-DDR50-1.8V-mode-support-for-BayTrail-e.patch
create mode 100644 features/soc/baytrail/mmc-support-whole-device-temporary-write-protection-.patch
diff --git a/features/soc/baytrail/baytrail.scc b/features/soc/baytrail/baytrail.scc
index 8ac3cfc..bd2bb4b 100644
--- a/features/soc/baytrail/baytrail.scc
+++ b/features/soc/baytrail/baytrail.scc
@@ -37,3 +37,10 @@ patch spi-pxa2xx-auto-switch-between-PIO-and-DMA-with-conf.patch
patch spi-modify-spidev_test-to-test-automatic-PIO-DMA-swi.patch
patch spi-pxa2xx-Add-new-ioctl-for-configuring-FIFO-trigge.patch
patch spi-modify-spidev_test-to-test-modifying-FIFO-trigge.patch
+patch mmc-sdhci-Preset-value-not-supported-in-Baytrail-eMM.patch
+patch mmc-sdhci-add-DDR50-1.8V-mode-support-for-BayTrail-e.patch
+patch mmc-sdhci-Force-BYT-SDCARD-host-to-run-with-SDR25-mo.patch
+patch mmc-block-refactor-read-only-handling.patch
+patch mmc-block-implement-write-request-blocking.patch
+patch mmc-support-whole-device-temporary-write-protection-.patch
+patch mmc-block-Fix-checkpatch.pl-warning.patch
diff --git a/features/soc/baytrail/mmc-block-Fix-checkpatch.pl-warning.patch b/features/soc/baytrail/mmc-block-Fix-checkpatch.pl-warning.patch
new file mode 100644
index 0000000..c30a27f
--- /dev/null
+++ b/features/soc/baytrail/mmc-block-Fix-checkpatch.pl-warning.patch
@@ -0,0 +1,31 @@
+From 91d5003e1687b17612e564fd41c3546444d69fa5 Mon Sep 17 00:00:00 2001
+From: Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad at intel.com>
+Date: Fri, 21 Aug 2015 12:34:31 +0800
+Subject: [PATCH 157/164] mmc: block: Fix checkpatch.pl warning
+
+This commit is to fix the result of running scripts/checkpatch.pl against
+0137-mmc-block-refactor-read-only-handling.patch
+
+Signed-off-by: Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad at intel.com>
+---
+ drivers/mmc/card/block.c | 4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
+index 9233aa5..aab78e9 100644
+--- a/drivers/mmc/card/block.c
++++ b/drivers/mmc/card/block.c
+@@ -269,8 +269,8 @@ static ssize_t power_ro_lock_store(struct device *dev,
+ /* Hardware WP affects both boot partitions */
+ list_for_each_entry(part_md, &md->part, part) {
+ if (part_md->area_type == MMC_BLK_DATA_AREA_BOOT) {
+- pr_info("%s: Locking boot partition ro until "
+- "next power on\n", part_md->disk->disk_name);
++ pr_info("%s: Locking boot partition ro until next power on\n",
++ part_md->disk->disk_name);
+ part_md->read_only |= MMC_RO_BOOT_WP;
+ update_disk_ro(part_md);
+ }
+--
+1.7.7.6
+
diff --git a/features/soc/baytrail/mmc-block-implement-write-request-blocking.patch b/features/soc/baytrail/mmc-block-implement-write-request-blocking.patch
new file mode 100644
index 0000000..cd50d1e
--- /dev/null
+++ b/features/soc/baytrail/mmc-block-implement-write-request-blocking.patch
@@ -0,0 +1,180 @@
+From 518fbeaeffe4c47f3d5d49c338f4f723bcab197b Mon Sep 17 00:00:00 2001
+From: Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad at intel.com>
+Date: Sun, 26 Jul 2015 13:09:23 +0800
+Subject: [PATCH 138/164] mmc: block: implement write request blocking
+
+This commit will enable write request blocking via
+/sys/block/mmcblkN/block_writes.
+When non-zero is written there, devices is synced, and then all write
+requests to device are errored out.
+
+This is unsafe. Use at own risk.
+
+Signed-off-by: Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad at intel.com>
+---
+ drivers/mmc/card/Kconfig | 13 +++++++
+ drivers/mmc/card/block.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 95 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig
+index 5562308..85dcc33 100644
+--- a/drivers/mmc/card/Kconfig
++++ b/drivers/mmc/card/Kconfig
+@@ -50,6 +50,19 @@ config MMC_BLOCK_BOUNCE
+
+ If unsure, say Y here.
+
++config MMC_BLOCK_WRB
++ bool "Support write request blocking on SD/MMC devices"
++ depends on MMC_BLOCK
++ default n
++ help
++ Enabling this adds 'block_writes' sysfs attribute to SD/MMC
++ block device. If 1 is written to that attribute, device is
++ immediately sync'ed, and all further write requests will be
++ errored out.
++
++ This is unsafe, and should not be used unless you know exactly
++ what you are doing.
++
+ config SDIO_UART
+ tristate "SDIO UART/GPS class support"
+ depends on TTY
+diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
+index 3e07095..3715530 100644
+--- a/drivers/mmc/card/block.c
++++ b/drivers/mmc/card/block.c
+@@ -105,6 +105,7 @@ struct mmc_blk_data {
+ #define MMC_RO_DEVICE BIT(0) /* underlying device is read only */
+ #define MMC_RO_FORCED BIT(1) /* read only forced */
+ #define MMC_RO_BOOT_WP BIT(2) /* boot partitions write protected */
++#define MMC_RO_WRB BIT(3) /* write requests are blocked */
+
+ unsigned int part_type;
+ unsigned int name_idx;
+@@ -122,6 +123,9 @@ struct mmc_blk_data {
+ unsigned int part_curr;
+ struct device_attribute force_ro;
+ struct device_attribute power_ro_lock;
++#ifdef CONFIG_MMC_BLOCK_WRB
++ struct device_attribute block_writes;
++#endif
+ int area_type;
+ };
+
+@@ -311,6 +315,56 @@ static ssize_t force_ro_store(struct device *dev, struct device_attribute *attr,
+ return count;
+ }
+
++#ifdef CONFIG_MMC_BLOCK_WRB
++static ssize_t block_writes_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ int ret;
++ struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
++
++ ret = sprintf(buf, "%d\n", !!(md->read_only & MMC_RO_WRB));
++ mmc_blk_put(md);
++ return ret;
++}
++
++static ssize_t block_writes_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t count)
++{
++ struct mmc_blk_data *md;
++ unsigned long set;
++
++ if (kstrtoul(buf, 0, &set))
++ return -EINVAL;
++
++ md = mmc_blk_get(dev_to_disk(dev));
++
++ if (!set)
++ md->read_only &= ~MMC_RO_WRB;
++ else {
++ struct disk_part_iter piter;
++ struct hd_struct *part;
++ struct block_device *bdev;
++
++ disk_part_iter_init(&piter, md->disk, DISK_PITER_INCL_PART0);
++ while ((part = disk_part_iter_next(&piter))) {
++ bdev = bdget(part_devt(part));
++ if (bdev) {
++ fsync_bdev(bdev);
++ bdput(bdev);
++ }
++ }
++ disk_part_iter_exit(&piter);
++
++ md->read_only |= MMC_RO_WRB;
++ }
++
++ update_disk_ro(md);
++
++ mmc_blk_put(md);
++ return count;
++}
++#endif
++
+ static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
+ {
+ struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
+@@ -2002,6 +2056,16 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
+ /* claim host only for the first request */
+ mmc_get_card(card);
+
++#ifdef CONFIG_MMC_BLOCK_WRB
++ if (req && (md->read_only & MMC_RO_WRB) &&
++ ((cmd_flags & REQ_DISCARD) || rq_data_dir(req) == WRITE)) {
++
++ blk_end_request_all(req, -EIO);
++ ret = 0;
++ goto out;
++ }
++#endif
++
+ ret = mmc_blk_part_switch(card, md);
+ if (ret) {
+ if (req) {
+@@ -2281,6 +2345,10 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
+ mmc_packed_clean(&md->queue);
+ if (md->disk->flags & GENHD_FL_UP) {
+ device_remove_file(disk_to_dev(md->disk), &md->force_ro);
++#ifdef CONFIG_MMC_BLOCK_WRB
++ device_remove_file(disk_to_dev(md->disk),
++ &md->block_writes);
++#endif
+ if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
+ card->ext_csd.boot_ro_lockable)
+ device_remove_file(disk_to_dev(md->disk),
+@@ -2320,6 +2388,16 @@ static int mmc_add_disk(struct mmc_blk_data *md)
+ ret = device_create_file(disk_to_dev(md->disk), &md->force_ro);
+ if (ret)
+ goto force_ro_fail;
++#ifdef CONFIG_MMC_BLOCK_WRB
++ md->block_writes.show = block_writes_show;
++ md->block_writes.store = block_writes_store;
++ sysfs_attr_init(&md->block_writes.attr);
++ md->block_writes.attr.name = "block_writes";
++ md->block_writes.attr.mode = S_IRUGO | S_IWUSR;
++ ret = device_create_file(disk_to_dev(md->disk), &md->block_writes);
++ if (ret)
++ goto block_writes_fail;
++#endif
+
+ if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
+ card->ext_csd.boot_ro_lockable) {
+@@ -2344,6 +2422,10 @@ static int mmc_add_disk(struct mmc_blk_data *md)
+ return ret;
+
+ power_ro_lock_fail:
++#ifdef CONFIG_MMC_BLOCK_WRB
++ device_remove_file(disk_to_dev(md->disk), &md->block_writes);
++block_writes_fail:
++#endif
+ device_remove_file(disk_to_dev(md->disk), &md->force_ro);
+ force_ro_fail:
+ del_gendisk(md->disk);
+--
+1.7.7.6
+
diff --git a/features/soc/baytrail/mmc-block-refactor-read-only-handling.patch b/features/soc/baytrail/mmc-block-refactor-read-only-handling.patch
new file mode 100644
index 0000000..4a663ce
--- /dev/null
+++ b/features/soc/baytrail/mmc-block-refactor-read-only-handling.patch
@@ -0,0 +1,214 @@
+From b0c00075c2fe613b91f500a0318a46e7c7e56b68 Mon Sep 17 00:00:00 2001
+From: Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad at intel.com>
+Date: Sun, 26 Jul 2015 12:35:21 +0800
+Subject: [PATCH 137/164] mmc: block: refactor read-only handling
+
+There are several reasons why gendisk corresponding to SD/eMMC card or
+hardware partition is read-only for the system:
+- underlying device is readonly (due to write protect GPIO, or due to
+ card lacks support for write commands),
+- due to card-level write protection (currently supported only for eMMC
+ boot partitions),
+- due to software 'force_ro' attribute (currently enabled by default for
+ eMMC boot partitions).
+
+This is managed indirectly, via gendisk's read-only flag.
+
+Since more possible read-only reasons are about to be added, need to
+replace that with explicit handling.
+
+This patch turns 'read_only' field of struct mmc_blk_data into a bitmask,
+with individual bits representing possible read-only reasons. Gendisk
+is marked read-only when at least one bit is set in the mask, and
+is marked read-write when last bit is cleared.
+
+Signed-off-by: Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad at intel.com>
+---
+ drivers/mmc/card/block.c | 96 ++++++++++++++++++++++++++++++---------------
+ 1 files changed, 64 insertions(+), 32 deletions(-)
+
+diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
+index b1e21fc..3e07095 100644
+--- a/drivers/mmc/card/block.c
++++ b/drivers/mmc/card/block.c
+@@ -102,6 +102,10 @@ struct mmc_blk_data {
+
+ unsigned int usage;
+ unsigned int read_only;
++#define MMC_RO_DEVICE BIT(0) /* underlying device is read only */
++#define MMC_RO_FORCED BIT(1) /* read only forced */
++#define MMC_RO_BOOT_WP BIT(2) /* boot partitions write protected */
++
+ unsigned int part_type;
+ unsigned int name_idx;
+ unsigned int reset_done;
+@@ -190,6 +194,11 @@ static void mmc_blk_put(struct mmc_blk_data *md)
+ mutex_unlock(&open_lock);
+ }
+
++static inline void update_disk_ro(struct mmc_blk_data *md)
++{
++ set_disk_ro(md->disk, !!md->read_only);
++}
++
+ static ssize_t power_ro_lock_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+@@ -227,29 +236,41 @@ static ssize_t power_ro_lock_store(struct device *dev,
+
+ mmc_get_card(card);
+
++ if (card->ext_csd.boot_ro_lock & (EXT_CSD_BOOT_WP_B_PERM_WP_EN |
++ EXT_CSD_BOOT_WP_B_PWR_WP_EN)) {
++ mmc_put_card(card);
++ goto out;
++ }
++
+ ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
+ card->ext_csd.boot_ro_lock |
+ EXT_CSD_BOOT_WP_B_PWR_WP_EN,
+ card->ext_csd.part_time);
+- if (ret)
++ if (ret) {
++ mmc_put_card(card);
+ pr_err("%s: Locking boot partition ro until next power on failed: %d\n", md->disk->disk_name, ret);
+- else
+- card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN;
++ goto out;
++ }
+
++ card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN;
+ mmc_put_card(card);
+
+- if (!ret) {
+- pr_info("%s: Locking boot partition ro until next power on\n",
+- md->disk->disk_name);
+- set_disk_ro(md->disk, 1);
++ pr_info("%s: Locking boot partition ro until next power on\n",
++ md->disk->disk_name);
++ md->read_only |= MMC_RO_BOOT_WP;
++ update_disk_ro(md);
+
+- list_for_each_entry(part_md, &md->part, part)
+- if (part_md->area_type == MMC_BLK_DATA_AREA_BOOT) {
+- pr_info("%s: Locking boot partition ro until next power on\n", part_md->disk->disk_name);
+- set_disk_ro(part_md->disk, 1);
+- }
++ /* Hardware WP affects both boot partitions */
++ list_for_each_entry(part_md, &md->part, part) {
++ if (part_md->area_type == MMC_BLK_DATA_AREA_BOOT) {
++ pr_info("%s: Locking boot partition ro until "
++ "next power on\n", part_md->disk->disk_name);
++ part_md->read_only |= MMC_RO_BOOT_WP;
++ update_disk_ro(part_md);
++ }
+ }
+
++out:
+ mmc_blk_put(md);
+ return count;
+ }
+@@ -260,9 +281,10 @@ static ssize_t force_ro_show(struct device *dev, struct device_attribute *attr,
+ int ret;
+ struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+
+- ret = snprintf(buf, PAGE_SIZE, "%d\n",
+- get_disk_ro(dev_to_disk(dev)) ^
+- md->read_only);
++ /* Show 1 only if 'force_ro' is the only reason of device
++ * being read only.
++ */
++ ret = sprintf(buf, "%d\n", md->read_only == MMC_RO_FORCED);
+ mmc_blk_put(md);
+ return ret;
+ }
+@@ -270,20 +292,23 @@ static ssize_t force_ro_show(struct device *dev, struct device_attribute *attr,
+ static ssize_t force_ro_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+- int ret;
+- char *end;
+- struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+- unsigned long set = simple_strtoul(buf, &end, 0);
+- if (end == buf) {
+- ret = -EINVAL;
+- goto out;
+- }
++ struct mmc_blk_data *md;
++ unsigned long set;
++
++ if (kstrtoul(buf, 0, &set))
++ return -EINVAL;
++
++ md = mmc_blk_get(dev_to_disk(dev));
++
++ if (set)
++ md->read_only |= MMC_RO_FORCED;
++ else
++ md->read_only &= ~MMC_RO_FORCED;
++
++ update_disk_ro(md);
+
+- set_disk_ro(dev_to_disk(dev), set || md->read_only);
+- ret = count;
+-out:
+ mmc_blk_put(md);
+- return ret;
++ return count;
+ }
+
+ static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
+@@ -2032,7 +2057,7 @@ static inline int mmc_blk_readonly(struct mmc_card *card)
+ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
+ struct device *parent,
+ sector_t size,
+- bool default_ro,
++ bool force_ro,
+ const char *subname,
+ int area_type)
+ {
+@@ -2069,7 +2094,14 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
+ * Set the read-only status based on the supported commands
+ * and the write protect switch.
+ */
+- md->read_only = mmc_blk_readonly(card);
++ if (mmc_blk_readonly(card))
++ md->read_only |= MMC_RO_DEVICE;
++ if (force_ro)
++ md->read_only |= MMC_RO_FORCED;
++ if (area_type == MMC_BLK_DATA_AREA_BOOT &&
++ (card->ext_csd.boot_ro_lock & (EXT_CSD_BOOT_WP_B_PERM_WP_EN |
++ EXT_CSD_BOOT_WP_B_PWR_WP_EN)))
++ md->read_only |= MMC_RO_BOOT_WP;
+
+ md->disk = alloc_disk(perdev_minors);
+ if (md->disk == NULL) {
+@@ -2094,7 +2126,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
+ md->disk->private_data = md;
+ md->disk->queue = md->queue.queue;
+ md->disk->driverfs_dev = parent;
+- set_disk_ro(md->disk, md->read_only || default_ro);
++ update_disk_ro(md);
+ if (area_type & MMC_BLK_DATA_AREA_RPMB)
+ md->disk->flags |= GENHD_FL_NO_PART_SCAN;
+
+@@ -2182,14 +2214,14 @@ static int mmc_blk_alloc_part(struct mmc_card *card,
+ struct mmc_blk_data *md,
+ unsigned int part_type,
+ sector_t size,
+- bool default_ro,
++ bool force_ro,
+ const char *subname,
+ int area_type)
+ {
+ char cap_str[10];
+ struct mmc_blk_data *part_md;
+
+- part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro,
++ part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, force_ro,
+ subname, area_type);
+ if (IS_ERR(part_md))
+ return PTR_ERR(part_md);
+--
+1.7.7.6
+
diff --git a/features/soc/baytrail/mmc-sdhci-Force-BYT-SDCARD-host-to-run-with-SDR25-mo.patch b/features/soc/baytrail/mmc-sdhci-Force-BYT-SDCARD-host-to-run-with-SDR25-mo.patch
new file mode 100644
index 0000000..ea6a08f
--- /dev/null
+++ b/features/soc/baytrail/mmc-sdhci-Force-BYT-SDCARD-host-to-run-with-SDR25-mo.patch
@@ -0,0 +1,80 @@
+From 7650d0fbd3ceaae2aff81ee50ea8cb0f0b8eefbe Mon Sep 17 00:00:00 2001
+From: "Chew, Kean Ho" <kean.ho.chew at intel.com>
+Date: Mon, 23 Dec 2013 16:14:27 +0800
+Subject: [PATCH 031/164] mmc: sdhci: Force BYT SDCARD host to run with SDR25
+ mode
+
+The clock appears to be unstable when SDCARD host running with
+DDR50 mode, thus causing CRC issue. This is to introduce a new
+quirk to force host with broken DDR50 mode to run with SDR25
+mode.
+
+Signed-off-by: Chew, Kean Ho <kean.ho.chew at intel.com>
+Signed-off-by: Chew, Chiau Ee <chiau.ee.chew at intel.com>
+Signed-off-by: Maurice Petallo <mauricex.r.petallo at intel.com>
+---
+ drivers/mmc/host/sdhci-acpi.c | 3 ++-
+ drivers/mmc/host/sdhci-pci.c | 3 ++-
+ drivers/mmc/host/sdhci.c | 3 ++-
+ include/linux/mmc/sdhci.h | 2 ++
+ 4 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
+index 88863bf..90b1f68 100644
+--- a/drivers/mmc/host/sdhci-acpi.c
++++ b/drivers/mmc/host/sdhci-acpi.c
+@@ -133,7 +133,8 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
+
+ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = {
+ .flags = SDHCI_ACPI_SD_CD | SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL |
+ SDHCI_ACPI_RUNTIME_PM,
+- .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON,
++ .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON |
++ SDHCI_QUIRK2_BROKEN_DDR50,
+ };
+
+ struct sdhci_acpi_uid_slot {
+diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
+index dda7dd0..82a4019 100644
+--- a/drivers/mmc/host/sdhci-pci.c
++++ b/drivers/mmc/host/sdhci-pci.c
+@@ -293,7 +293,8 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
+ };
+
+ static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
+- .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON,
++ .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON |
++ SDHCI_QUIRK2_BROKEN_DDR50,
+ .allow_runtime_pm = true,
+ .own_cd_for_runtime_pm = true,
+ };
+diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
+index 22eccbf..b505882 100644
+--- a/drivers/mmc/host/sdhci.c
++++ b/drivers/mmc/host/sdhci.c
+@@ -3022,7 +3022,8 @@ int sdhci_add_host(struct sdhci_host *host)
+ } else if (caps[1] & SDHCI_SUPPORT_SDR50)
+ mmc->caps |= MMC_CAP_UHS_SDR50;
+
+- if (caps[1] & SDHCI_SUPPORT_DDR50)
++ if ((caps[1] & SDHCI_SUPPORT_DDR50) &&
++ !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50))
+ mmc->caps |= MMC_CAP_UHS_DDR50;
+
+ /* Does the host need tuning for SDR50? */
+diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
+index 362927c4..19353dd 100644
+--- a/include/linux/mmc/sdhci.h
++++ b/include/linux/mmc/sdhci.h
+@@ -100,6 +100,8 @@ struct sdhci_host {
+ #define SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1<<5)
+ /* Controller does not support HS200 */
+ #define SDHCI_QUIRK2_BROKEN_HS200 (1<<6)
++/* Controller has a broken DDR50 Time Spec */
++#define SDHCI_QUIRK2_BROKEN_DDR50 (1<<7)
+
+ int irq; /* Device IRQ */
+ void __iomem *ioaddr; /* Mapped address */
+--
+1.7.7.6
+
diff --git a/features/soc/baytrail/mmc-sdhci-Preset-value-not-supported-in-Baytrail-eMM.patch b/features/soc/baytrail/mmc-sdhci-Preset-value-not-supported-in-Baytrail-eMM.patch
new file mode 100644
index 0000000..64d35cd
--- /dev/null
+++ b/features/soc/baytrail/mmc-sdhci-Preset-value-not-supported-in-Baytrail-eMM.patch
@@ -0,0 +1,47 @@
+From d6e4257c98dc4633fd707e80d696430f2acd8053 Mon Sep 17 00:00:00 2001
+From: Maurice Petallo <mauricex.r.petallo at intel.com>
+Date: Tue, 8 Jul 2014 19:11:00 +0800
+Subject: [PATCH 025/164] mmc: sdhci: Preset value not supported in Baytrail
+ eMMC
+
+"SDHCI_QUIRK2_PRESET_VALUE_BROKEN" quirk is added to prohibit
+preset value enabling for Baytrail eMMC controller.
+
+Signed-off-by: Maurice Petallo <mauricex.r.petallo at intel.com>
+Acked-by: Adrian Hunter <adrian.hunter at intel.com>
+Signed-off-by: Ulf Hansson <ulf.hansson at linaro.org>
+(cherry picked from commit d61b59461b0cd0106f03e566d537b9072029e059)
+
+Signed-off-by: Maurice Petallo <mauricex.r.petallo at intel.com>
+---
+ drivers/mmc/host/sdhci-acpi.c | 1 +
+ drivers/mmc/host/sdhci-pci.c | 1 +
+ 2 files changed, 2 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
+index 9ce17f6..2a35338 100644
+--- a/drivers/mmc/host/sdhci-acpi.c
++++ b/drivers/mmc/host/sdhci-acpi.c
+@@ -118,6 +118,7 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = {
+ .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | MMC_CAP_HW_RESET,
+ .caps2 = MMC_CAP2_HC_ERASE_SZ,
+ .flags = SDHCI_ACPI_RUNTIME_PM,
++ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+ };
+
+ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
+diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
+index 19bfa0a..4424238 100644
+--- a/drivers/mmc/host/sdhci-pci.c
++++ b/drivers/mmc/host/sdhci-pci.c
+@@ -283,6 +283,7 @@ static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
+ static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = {
+ .allow_runtime_pm = true,
+ .probe_slot = byt_emmc_probe_slot,
++ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+ };
+
+ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
+--
+1.7.7.6
+
diff --git a/features/soc/baytrail/mmc-sdhci-add-DDR50-1.8V-mode-support-for-BayTrail-e.patch b/features/soc/baytrail/mmc-sdhci-add-DDR50-1.8V-mode-support-for-BayTrail-e.patch
new file mode 100644
index 0000000..8ee105f
--- /dev/null
+++ b/features/soc/baytrail/mmc-sdhci-add-DDR50-1.8V-mode-support-for-BayTrail-e.patch
@@ -0,0 +1,50 @@
+From 9d4bcd4f06fe345ba6ee5b0ed82fda836ecf090c Mon Sep 17 00:00:00 2001
+From: Maurice Petallo <mauricex.r.petallo at intel.com>
+Date: Tue, 8 Jul 2014 19:11:01 +0800
+Subject: [PATCH 026/164] mmc: sdhci: add DDR50 1.8V mode support for BayTrail
+ eMMC Controller
+
+This is to enable DDR50 bus speed mode with 1.8V signaling capability
+for BayTrail ACPI and PCI mode eMMC Controller.
+
+Signed-off-by: Maurice Petallo <mauricex.r.petallo at intel.com>
+Acked-by: Adrian Hunter <adrian.hunter at intel.com>
+Signed-off-by: Ulf Hansson <ulf.hansson at linaro.org>
+(cherry picked from commit f25c33724d1512a72554c0ad4cb70b43ba15374e)
+
+Signed-off-by: Maurice Petallo <mauricex.r.petallo at intel.com>
+---
+ drivers/mmc/host/sdhci-acpi.c | 3 ++-
+ drivers/mmc/host/sdhci-pci.c | 2 +-
+ 2 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
+index 2a35338..88863bf 100644
+--- a/drivers/mmc/host/sdhci-acpi.c
++++ b/drivers/mmc/host/sdhci-acpi.c
+@@ -115,7 +115,8 @@ static const struct sdhci_acpi_chip sdhci_acpi_chip_int = {
+
+ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = {
+ .chip = &sdhci_acpi_chip_int,
+- .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | MMC_CAP_HW_RESET,
++ .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
++ MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR,
+ .caps2 = MMC_CAP2_HC_ERASE_SZ,
+ .flags = SDHCI_ACPI_RUNTIME_PM,
+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
+index 4424238..dda7dd0 100644
+--- a/drivers/mmc/host/sdhci-pci.c
++++ b/drivers/mmc/host/sdhci-pci.c
+@@ -268,7 +268,7 @@ static void sdhci_pci_int_hw_reset(struct sdhci_host *host)
+ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
+ {
+ slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
+- MMC_CAP_HW_RESET;
++ MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR;
+ slot->host->mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ;
+ slot->hw_reset = sdhci_pci_int_hw_reset;
+ return 0;
+--
+1.7.7.6
+
diff --git a/features/soc/baytrail/mmc-support-whole-device-temporary-write-protection-.patch b/features/soc/baytrail/mmc-support-whole-device-temporary-write-protection-.patch
new file mode 100644
index 0000000..d5f4ece
--- /dev/null
+++ b/features/soc/baytrail/mmc-support-whole-device-temporary-write-protection-.patch
@@ -0,0 +1,367 @@
+From 639b25dce5cf6534503dfdf7cf1015c478a17664 Mon Sep 17 00:00:00 2001
+From: Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad at intel.com>
+Date: Sun, 26 Jul 2015 14:40:37 +0800
+Subject: [PATCH 140/164] mmc: support whole-device temporary write protection
+ over CSD bits 13:12
+
+This commit add support for eMMC whole-device temporary write protection
+feature. mmcblk device get new "card_wp" attribute, that can be used to read
+and change device-side write protection.
+
+For safety reasons, setting permanent write protection is not supported.
+
+Signed-off-by: Wan Ahmad Zainie <wan.ahmad.zainie.wan.mohamad at intel.com>
+---
+ drivers/mmc/Kconfig | 1 +
+ drivers/mmc/card/block.c | 81 +++++++++++++++++++++++++++++++++++++++
+ drivers/mmc/core/mmc.c | 2 +
+ drivers/mmc/core/mmc_ops.c | 91 ++++++++++++++++++++++++++++++++++++++++++++
+ drivers/mmc/core/mmc_ops.h | 1 +
+ drivers/mmc/core/sd.c | 4 ++
+ include/linux/mmc/card.h | 4 +-
+ include/linux/mmc/core.h | 1 +
+ 8 files changed, 184 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
+index f2eeb38..74076bc 100644
+--- a/drivers/mmc/Kconfig
++++ b/drivers/mmc/Kconfig
+@@ -5,6 +5,7 @@
+ menuconfig MMC
+ tristate "MMC/SD/SDIO card support"
+ depends on HAS_IOMEM
++ select CRC7
+ help
+ This selects MultiMediaCard, Secure Digital and Secure
+ Digital I/O support.
+diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
+index 3715530..9233aa5 100644
+--- a/drivers/mmc/card/block.c
++++ b/drivers/mmc/card/block.c
+@@ -106,6 +106,7 @@ struct mmc_blk_data {
+ #define MMC_RO_FORCED BIT(1) /* read only forced */
+ #define MMC_RO_BOOT_WP BIT(2) /* boot partitions write protected */
+ #define MMC_RO_WRB BIT(3) /* write requests are blocked */
++#define MMC_RO_CARD_WP BIT(4) /* card is write protected via CSD */
+
+ unsigned int part_type;
+ unsigned int name_idx;
+@@ -126,6 +127,7 @@ struct mmc_blk_data {
+ #ifdef CONFIG_MMC_BLOCK_WRB
+ struct device_attribute block_writes;
+ #endif
++ struct device_attribute card_wp;
+ int area_type;
+ };
+
+@@ -365,6 +367,69 @@ static ssize_t block_writes_store(struct device *dev,
+ }
+ #endif
+
++static ssize_t card_wp_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ int val, ret;
++ struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
++ struct mmc_card *card = md->queue.card;
++
++ if (card->csd.perm_wp)
++ val = 2;
++ else if (card->csd.temp_wp)
++ val = 1;
++ else
++ val = 0;
++
++ ret = sprintf(buf, "%d\n", val);
++ mmc_blk_put(md);
++ return ret;
++}
++
++static ssize_t card_wp_store(struct device *dev, struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct mmc_blk_data *md, *part_md;
++ struct mmc_card *card;
++ unsigned long set;
++ ssize_t ret;
++
++ if (kstrtoul(buf, 0, &set) || (set != 0 && set != 1))
++ return -EINVAL;
++
++ md = mmc_blk_get(dev_to_disk(dev));
++ card = md->queue.card;
++ mmc_get_card(card);
++
++ if (card->csd.temp_wp == set)
++ goto out_ok;
++
++ ret = mmc_set_card_wp(card, set);
++ if (ret)
++ goto out;
++
++ if (card->csd.perm_wp || card->csd.temp_wp)
++ md->read_only |= MMC_RO_CARD_WP;
++ else
++ md->read_only &= ~MMC_RO_CARD_WP;
++ update_disk_ro(md);
++
++ /* propagate to all hw partitions over the same device */
++ list_for_each_entry(part_md, &md->part, part) {
++ if (card->csd.perm_wp || card->csd.temp_wp)
++ part_md->read_only |= MMC_RO_CARD_WP;
++ else
++ part_md->read_only &= ~MMC_RO_CARD_WP;
++ update_disk_ro(part_md);
++ }
++out_ok:
++ ret = count;
++out:
++ mmc_put_card(card);
++ mmc_blk_put(md);
++ return ret;
++}
++
+ static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
+ {
+ struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
+@@ -2166,6 +2231,8 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
+ (card->ext_csd.boot_ro_lock & (EXT_CSD_BOOT_WP_B_PERM_WP_EN |
+ EXT_CSD_BOOT_WP_B_PWR_WP_EN)))
+ md->read_only |= MMC_RO_BOOT_WP;
++ if (card->csd.perm_wp || card->csd.temp_wp)
++ md->read_only |= MMC_RO_CARD_WP;
+
+ md->disk = alloc_disk(perdev_minors);
+ if (md->disk == NULL) {
+@@ -2349,6 +2416,7 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
+ device_remove_file(disk_to_dev(md->disk),
+ &md->block_writes);
+ #endif
++ device_remove_file(disk_to_dev(md->disk), &md->card_wp);
+ if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
+ card->ext_csd.boot_ro_lockable)
+ device_remove_file(disk_to_dev(md->disk),
+@@ -2380,6 +2448,7 @@ static int mmc_add_disk(struct mmc_blk_data *md)
+ struct mmc_card *card = md->queue.card;
+
+ add_disk(md->disk);
++
+ md->force_ro.show = force_ro_show;
+ md->force_ro.store = force_ro_store;
+ sysfs_attr_init(&md->force_ro.attr);
+@@ -2388,6 +2457,7 @@ static int mmc_add_disk(struct mmc_blk_data *md)
+ ret = device_create_file(disk_to_dev(md->disk), &md->force_ro);
+ if (ret)
+ goto force_ro_fail;
++
+ #ifdef CONFIG_MMC_BLOCK_WRB
+ md->block_writes.show = block_writes_show;
+ md->block_writes.store = block_writes_store;
+@@ -2399,6 +2469,15 @@ static int mmc_add_disk(struct mmc_blk_data *md)
+ goto block_writes_fail;
+ #endif
+
++ md->card_wp.show = card_wp_show;
++ md->card_wp.store = card_wp_store;
++ sysfs_attr_init(&md->card_wp.attr);
++ md->card_wp.attr.name = "card_wp";
++ md->card_wp.attr.mode = S_IRUGO | S_IWUSR;
++ ret = device_create_file(disk_to_dev(md->disk), &md->card_wp);
++ if (ret)
++ goto card_wp_fail;
++
+ if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
+ card->ext_csd.boot_ro_lockable) {
+ umode_t mode;
+@@ -2422,6 +2501,8 @@ static int mmc_add_disk(struct mmc_blk_data *md)
+ return ret;
+
+ power_ro_lock_fail:
++ device_remove_file(disk_to_dev(md->disk), &md->card_wp);
++card_wp_fail:
+ #ifdef CONFIG_MMC_BLOCK_WRB
+ device_remove_file(disk_to_dev(md->disk), &md->block_writes);
+ block_writes_fail:
+diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
+index 98e9eb0..eff1b04 100644
+--- a/drivers/mmc/core/mmc.c
++++ b/drivers/mmc/core/mmc.c
+@@ -165,6 +165,8 @@ static int mmc_decode_csd(struct mmc_card *card)
+ csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
+ csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+ csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
++ csd->perm_wp = UNSTUFF_BITS(resp, 13, 1);
++ csd->temp_wp = UNSTUFF_BITS(resp, 12, 1);
+
+ if (csd->write_blkbits >= 9) {
+ a = UNSTUFF_BITS(resp, 42, 5);
+diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
+index e5b5eeb..2f2b29b 100644
+--- a/drivers/mmc/core/mmc_ops.c
++++ b/drivers/mmc/core/mmc_ops.c
+@@ -13,6 +13,7 @@
+ #include <linux/export.h>
+ #include <linux/types.h>
+ #include <linux/scatterlist.h>
++#include <linux/crc7.h>
+
+ #include <linux/mmc/host.h>
+ #include <linux/mmc/card.h>
+@@ -637,3 +638,93 @@ int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status)
+
+ return 0;
+ }
++
++int mmc_program_csd(struct mmc_card *card, u8 *csd_128be)
++{
++ struct mmc_request mrq = {NULL};
++ struct mmc_command cmd = {0};
++ struct mmc_data data = {0};
++ struct scatterlist sg;
++ void *data_buf;
++ int is_on_stack;
++ int len = 16;
++
++ is_on_stack = object_is_on_stack(csd_128be);
++ if (is_on_stack) {
++ /*
++ * dma onto stack is unsafe/nonportable, but callers to this
++ * routine normally provide temporary on-stack buffers ...
++ */
++ data_buf = kmalloc(len, GFP_KERNEL);
++ if (!data_buf)
++ return -ENOMEM;
++ memcpy(data_buf, csd_128be, len);
++ } else
++ data_buf = csd_128be;
++
++ mrq.cmd = &cmd;
++ mrq.data = &data;
++
++ cmd.opcode = MMC_PROGRAM_CSD;
++ cmd.arg = 0;
++ cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
++
++ data.blksz = len;
++ data.blocks = 1;
++ data.flags = MMC_DATA_WRITE;
++ data.sg = &sg;
++ data.sg_len = 1;
++
++ sg_init_one(&sg, data_buf, len);
++
++ mmc_set_data_timeout(&data, card);
++
++ mmc_wait_for_req(card->host, &mrq);
++
++ if (is_on_stack)
++ kfree(data_buf);
++
++ if (cmd.error)
++ return cmd.error;
++ if (data.error)
++ return data.error;
++
++ return 0;
++}
++
++int mmc_set_card_wp(struct mmc_card *card, int wp)
++{
++ u8 csd_be128[16];
++ int i, ret;
++
++ if (card->csd.temp_wp == !!wp)
++ return 0;
++
++ for (i = 0; i < 4; i++)
++ ((u32 *)csd_be128)[i] = cpu_to_be32(card->raw_csd[i]);
++
++ /* update bit 12 with new temp_wp value */
++ if (wp)
++ csd_be128[14] |= 0x10;
++ else
++ csd_be128[14] &= ~0x10;
++
++ /* set CRC7 into bits 7:1, and 1 into bit 0 */
++ csd_be128[15] = (crc7(0, csd_be128, 15) << 1) | 0x1;
++
++ ret = mmc_program_csd(card, csd_be128);
++
++ if (!ret) {
++ /* update cached csd without re-reading */
++ if (wp) {
++ card->raw_csd[3] |= BIT(12);
++ card->csd.temp_wp = 1;
++ } else {
++ card->raw_csd[3] &= ~BIT(12);
++ card->csd.temp_wp = 0;
++ }
++ }
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(mmc_set_card_wp);
+diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
+index 80ae9f4..47884d5 100644
+--- a/drivers/mmc/core/mmc_ops.h
++++ b/drivers/mmc/core/mmc_ops.h
+@@ -26,6 +26,7 @@ int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp);
+ int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
+ int mmc_bus_test(struct mmc_card *card, u8 bus_width);
+ int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status);
++int mmc_program_csd(struct mmc_card *card, u8 *csd_128be);
+
+ #endif
+
+diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
+index 692fdb1..3654766 100644
+--- a/drivers/mmc/core/sd.c
++++ b/drivers/mmc/core/sd.c
+@@ -130,6 +130,8 @@ static int mmc_decode_csd(struct mmc_card *card)
+ csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
+ csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+ csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
++ csd->perm_wp = UNSTUFF_BITS(resp, 13, 1);
++ csd->temp_wp = UNSTUFF_BITS(resp, 12, 1);
+
+ if (UNSTUFF_BITS(resp, 46, 1)) {
+ csd->erase_size = 1;
+@@ -170,6 +172,8 @@ static int mmc_decode_csd(struct mmc_card *card)
+ csd->r2w_factor = 4; /* Unused */
+ csd->write_blkbits = 9;
+ csd->write_partial = 0;
++ csd->perm_wp = UNSTUFF_BITS(resp, 13, 1);
++ csd->temp_wp = UNSTUFF_BITS(resp, 12, 1);
+ csd->erase_size = 1;
+ break;
+ default:
+diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
+index b730272..ce301b8 100644
+--- a/include/linux/mmc/card.h
++++ b/include/linux/mmc/card.h
+@@ -42,7 +42,9 @@ struct mmc_csd {
+ unsigned int read_partial:1,
+ read_misalign:1,
+ write_partial:1,
+- write_misalign:1;
++ write_misalign:1,
++ perm_wp:1,
++ temp_wp:1;
+ };
+
+ struct mmc_ext_csd {
+diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
+index 87079fc..de843f8 100644
+--- a/include/linux/mmc/core.h
++++ b/include/linux/mmc/core.h
+@@ -155,6 +155,7 @@ extern int __mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int, bool,
+ bool);
+ extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int);
+ extern int mmc_send_ext_csd(struct mmc_card *card, u8 *ext_csd);
++extern int mmc_set_card_wp(struct mmc_card *card, int wp);
+
+ #define MMC_ERASE_ARG 0x00000000
+ #define MMC_SECURE_ERASE_ARG 0x80000000
+--
+1.7.7.6
+
--
1.9.1
More information about the linux-yocto
mailing list