[PATCH 2/3] Add boot_enable sysfs attribute to select MMC boot operation partition

2013-04-19 Thread Neil Armstrong
Add sysfs attribute to select the eMMC boot mode operation according to
the eMMC 4.5 specifications.
Valid values are : 0 for disabled, 1 for first boot partition, 2 for
second boot partition, 7 for user area.

Signed-off-by: Neil Armstrong 
---
 drivers/mmc/card/block.c |   72
+-
 1 files changed, 71 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 5bab73b..e11c42e 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -114,6 +114,7 @@ struct mmc_blk_data {
  */
 unsigned intpart_curr;
 struct device_attribute force_ro;
+struct device_attribute boot_enable;
 struct device_attribute power_ro_lock;
 intarea_type;
 };
@@ -264,6 +265,23 @@ static ssize_t force_ro_show(struct device *dev,
struct device_attribute *attr,
 return ret;
 }
 
+static ssize_t boot_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+int ret;
+struct mmc_card *card;
+struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+
+md = mmc_blk_get(dev_to_disk(dev));
+card = md->queue.card;
+
+ret = snprintf(buf, PAGE_SIZE, "%d",
+(card->ext_csd.part_config &
+ EXT_CSD_PART_CONFIG_EN_MASK) >> 3);
+mmc_blk_put(md);
+return ret;
+}
+
 static ssize_t force_ro_store(struct device *dev, struct
device_attribute *attr,
   const char *buf, size_t count)
 {
@@ -283,6 +301,48 @@ out:
 return ret;
 }
 
+static ssize_t boot_enable_store(struct device *dev,
+  struct device_attribute *attr, const char *buf,
+  size_t count)
+{
+int ret;
+char *end;
+u8 part_config;
+struct mmc_card *card;
+struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+unsigned long set = simple_strtoul(buf, , 0);
+if (end == buf) {
+ret = -EINVAL;
+goto out;
+}
+
+md = mmc_blk_get(dev_to_disk(dev));
+card = md->queue.card;
+
+part_config = card->ext_csd.part_config;
+
+part_config &= EXT_CSD_PART_CONFIG_EN_MASK;
+part_config |= (set << 3) & EXT_CSD_PART_CONFIG_EN_MASK;
+
+mmc_claim_host(card->host);
+
+ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_PART_CONFIG, part_config,
+ card->ext_csd.part_time);
+
+mmc_release_host(card->host);
+
+if (ret)
+return ret;
+
+card->ext_csd.part_config = part_config;
+
+ret = count;
+out:
+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);
@@ -2202,6 +2262,15 @@ static int mmc_add_disk(struct mmc_blk_data *md)
 if (ret)
 goto force_ro_fail;
 
+md->boot_enable.show = boot_enable_show;
+md->boot_enable.store = boot_enable_store;
+sysfs_attr_init(>boot_enable.attr);
+md->boot_enable.attr.name = "boot_enable";
+md->boot_enable.attr.mode = S_IRUGO | S_IWUSR;
+ret = device_create_file(disk_to_dev(md->disk), >boot_enable);
+if (ret)
+goto boot_enable_fail;
+
 if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
  card->ext_csd.boot_ro_lockable) {
 umode_t mode;
@@ -2225,6 +2294,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), >boot_enable);
+boot_enable_fail:
 device_remove_file(disk_to_dev(md->disk), >force_ro);
 force_ro_fail:
 del_gendisk(md->disk);
@@ -2434,4 +2505,3 @@ module_exit(mmc_blk_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver");
-
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/3] Add boot_enable sysfs attribute to select MMC boot operation partition

2013-04-19 Thread Neil Armstrong
Add sysfs attribute to select the eMMC boot mode operation according to
the eMMC 4.5 specifications.
Valid values are : 0 for disabled, 1 for first boot partition, 2 for
second boot partition, 7 for user area.

Signed-off-by: Neil Armstrong narmstr...@neotion.com
---
 drivers/mmc/card/block.c |   72
+-
 1 files changed, 71 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 5bab73b..e11c42e 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -114,6 +114,7 @@ struct mmc_blk_data {
  */
 unsigned intpart_curr;
 struct device_attribute force_ro;
+struct device_attribute boot_enable;
 struct device_attribute power_ro_lock;
 intarea_type;
 };
@@ -264,6 +265,23 @@ static ssize_t force_ro_show(struct device *dev,
struct device_attribute *attr,
 return ret;
 }
 
+static ssize_t boot_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+int ret;
+struct mmc_card *card;
+struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+
+md = mmc_blk_get(dev_to_disk(dev));
+card = md-queue.card;
+
+ret = snprintf(buf, PAGE_SIZE, %d,
+(card-ext_csd.part_config 
+ EXT_CSD_PART_CONFIG_EN_MASK)  3);
+mmc_blk_put(md);
+return ret;
+}
+
 static ssize_t force_ro_store(struct device *dev, struct
device_attribute *attr,
   const char *buf, size_t count)
 {
@@ -283,6 +301,48 @@ out:
 return ret;
 }
 
+static ssize_t boot_enable_store(struct device *dev,
+  struct device_attribute *attr, const char *buf,
+  size_t count)
+{
+int ret;
+char *end;
+u8 part_config;
+struct mmc_card *card;
+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;
+}
+
+md = mmc_blk_get(dev_to_disk(dev));
+card = md-queue.card;
+
+part_config = card-ext_csd.part_config;
+
+part_config = EXT_CSD_PART_CONFIG_EN_MASK;
+part_config |= (set  3)  EXT_CSD_PART_CONFIG_EN_MASK;
+
+mmc_claim_host(card-host);
+
+ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_PART_CONFIG, part_config,
+ card-ext_csd.part_time);
+
+mmc_release_host(card-host);
+
+if (ret)
+return ret;
+
+card-ext_csd.part_config = part_config;
+
+ret = count;
+out:
+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);
@@ -2202,6 +2262,15 @@ static int mmc_add_disk(struct mmc_blk_data *md)
 if (ret)
 goto force_ro_fail;
 
+md-boot_enable.show = boot_enable_show;
+md-boot_enable.store = boot_enable_store;
+sysfs_attr_init(md-boot_enable.attr);
+md-boot_enable.attr.name = boot_enable;
+md-boot_enable.attr.mode = S_IRUGO | S_IWUSR;
+ret = device_create_file(disk_to_dev(md-disk), md-boot_enable);
+if (ret)
+goto boot_enable_fail;
+
 if ((md-area_type  MMC_BLK_DATA_AREA_BOOT) 
  card-ext_csd.boot_ro_lockable) {
 umode_t mode;
@@ -2225,6 +2294,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-boot_enable);
+boot_enable_fail:
 device_remove_file(disk_to_dev(md-disk), md-force_ro);
 force_ro_fail:
 del_gendisk(md-disk);
@@ -2434,4 +2505,3 @@ module_exit(mmc_blk_exit);
 
 MODULE_LICENSE(GPL);
 MODULE_DESCRIPTION(Multimedia Card (MMC) block device driver);
-
-- 
1.7.0.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/