mmc: core: select the operation mode with sysfs
PATCH v3 1/1 mmc: core: select the operation mode with sysfs
This patch is support the sysfs for operation mode.
There are two operation modes(open-ended/pre-defined). Now, operation mode is selected only one at the compile time.
But using this patch, we can change the operation mode with node at runtime.
* pre-defined mode
echo 1 > /sys/class/mmc_host/mmc0/pre_defined_op
* open-ended mode
echo 0 > /sys/class/mmc_host/mmc0/pre_defined_op
Signed-off-by Jaehoon Chung <[email protected]>
Signed-off-by Kyungmin Park <[email protected]>
---
Changelog V3:
- Add the mmc_change_operation_mode()
Changelog v2:
- Add the check point in mmc_cmd23_store()
(If host controller didn't support CMD23, need not to change the ops-mode.)
drivers/mmc/card/block.c | 19 +++++++++++++++++++ drivers/mmc/core/host.c | 39 +++++++++++++++++++++++++++++++++++++++ include/linux/mmc/card.h | 1 + include/linux/mmc/host.h | 3 +++ 4 files changed, 62 insertions(+), 0 deletions(-)
drivers/mmc/card/block.c +19 -0
@@ -1765,6 +1765,25 @@ static const struct mmc_fixup blk_fixups[] = END_FIXUP }; +void mmc_change_operation_mode (struct mmc_card *card,int val) +{ +struct mmc_blk_data *md =mmc_get_drvdata (card); + +if (mmc_host_cmd23 (card->host)) { +if (mmc_card_mmc (card) || + (mmc_card_sd (card) && + card->scr.cmds &SD_SCR_CMD23_SUPPORT )) { +if (val) { + md->flags |=MMC_BLK_CMD23 ; + card->host->pre_defined_op = val; + }else { + md->flags &= ~MMC_BLK_CMD23 ; + card->host->pre_defined_op = val; + } + } + } +} +static int mmc_blk_probe (struct mmc_card *card) {struct mmc_blk_data *md, *part_md;
drivers/mmc/core/host.c +39 -0
@@ -293,6 +293,41 @@ static inline void mmc_host_clk_sysfs_init(struct mmc_host *host)#endif +static ssize_t mmc_cmd23_show (struct device *dev, +struct device_attribute *attr,char *buf) +{ +struct mmc_host *host =cls_dev_to_mmc_host (dev); +return snprintf (buf,PAGE_SIZE ,"%d\n" , host->pre_defined_op); +} + +static ssize_t mmc_cmd23_store (struct device *dev, +struct device_attribute *attr,const char *buf,size_t count) +{ +struct mmc_host *host =cls_dev_to_mmc_host (dev); +int value; +unsigned long flags; + +if (kstrtoint (buf,0 , &value)) +return -EINVAL ; + +spin_lock_irqsave (&host->lock, flags); +mmc_change_operation_mode (host->card, value); +spin_unlock_irqrestore (&host->lock, flags); +return count; +} + +static inline void mmc_host_cmd23_sysfs_init (struct mmc_host *host) +{ + host->pre_defined_attr.show = mmc_cmd23_show; + host->pre_defined_attr.store = mmc_cmd23_store; +sysfs_attr_init (&host->pre_defined_attr.attr); + host->pre_defined_attr.attr.name ="pre_defined_op" ; + host->pre_defined_attr.attr.mode =S_IRUGO |S_IWUSR ; +if (device_create_file (&host->class_dev, &host->pre_defined_attr)) +pr_err ("%s: Failed to create pre_defined_op sysfs entry\n" , +mmc_hostname (host)); +} +/** * mmc_alloc_host - initialise the per-host structure. * @extra: sizeof private data structure
@@ -381,6 +416,10 @@ int mmc_add_host(struct mmc_host *host)#endif mmc_host_clk_sysfs_init (host); +if (host->caps &MMC_CAP_CMD23 ) + host->pre_defined_op =1 ; +mmc_host_cmd23_sysfs_init (host); +mmc_start_host (host);register_pm_notifier (&host->pm_notify);
include/linux/mmc/card.h +1 -0
@@ -485,5 +485,6 @@ extern void mmc_unregister_driver(struct mmc_driver *);extern void mmc_fixup_device (struct mmc_card *card,const struct mmc_fixup *table); +extern void mmc_change_operation_mode (struct mmc_card *card,int val);#endif /* LINUX_MMC_CARD_H */
include/linux/mmc/host.h +3 -0
@@ -258,6 +258,9 @@ struct mmc_host {#define MMC_CAP2_HS200 (MMC_CAP2_HS200_1_8V_SDR | \ MMC_CAP2_HS200_1_2V_SDR) +struct device_attribute pre_defined_attr; +int pre_defined_op;/* CMD23 should be use or not */ +mmc_pm_flag_t pm_caps;/* supported pm features */ unsigned int power_notify_type;#define MMC_HOST_PW_NOTIFY_NONE 0