On Fri, 29 Sept 2023 at 21:17, Vincent Whitchurch <vincent.whitchurch@xxxxxxxx> wrote: > > During board verification, there is a need to test the various supported > eMMC/SD speed modes. However, since the framework chooses the best mode > supported by the card and the host controller's caps, this currently > necessitates changing the devicetree for every iteration. > > Allow the various speed mode host capabilities to be modified via > debugfs in order to allow easier hardware verification. The values to > be written are the raw MMC_CAP* values from include/linux/mmc/host.h. > This is rather low-level, and these defines are not guaranteed to be > stable, but it is perhaps good enough for the intended use case. > > MMC_CAP_AGGRESSIVE_PM can also be set, in order to be able to > re-initialize the card without having to physically remove and re-insert > it. > > /sys/kernel/debug/mmc0# grep timing ios > timing spec: 9 (mmc HS200) > > // Turn on MMC_CAP_AGGRESSIVE_PM and re-trigger runtime suspend > /sys/kernel/debug/mmc0# echo $(($(cat caps) | (1 << 7))) > caps > /sys/kernel/debug/mmc0# echo on > /sys/bus/mmc/devices/mmc0\:0001/power/control > /sys/kernel/debug/mmc0# echo auto > /sys/bus/mmc/devices/mmc0\:0001/power/control > > // MMC_CAP2_HS200_1_8V_SDR > /sys/kernel/debug/mmc0# echo $(($(cat caps2) & ~(1 << 5))) > caps2 $(($(cat caps2) & ~(1 << 5))) looks complicated, does it use echo DDR52 > caps2? > /sys/kernel/debug/mmc0# echo on > /sys/bus/mmc/devices/mmc0\:0001/power/control > /sys/kernel/debug/mmc0# grep timing ios > timing spec: 8 (mmc DDR52) > > Signed-off-by: Vincent Whitchurch <vincent.whitchurch@xxxxxxxx> > --- > drivers/mmc/core/debugfs.c | 51 ++++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 49 insertions(+), 2 deletions(-) > > diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c > index 2c97b94aab23..1642ea72d22c 100644 > --- a/drivers/mmc/core/debugfs.c > +++ b/drivers/mmc/core/debugfs.c > @@ -12,9 +12,12 @@ > #include <linux/slab.h> > #include <linux/stat.h> > #include <linux/fault-inject.h> > +#include <linux/time.h> > > #include <linux/mmc/card.h> > #include <linux/mmc/host.h> > +#include <linux/mmc/mmc.h> > +#include <linux/mmc/sd.h> > > #include "core.h" > #include "card.h" > @@ -298,6 +301,49 @@ static const struct file_operations mmc_err_stats_fops = { > .release = single_release, > }; > > +static int mmc_caps_get(void *data, u64 *val) > +{ > + *val = *(u32 *)data; > + return 0; > +} > + > +static int mmc_caps_set(void *data, u64 val) > +{ > + u32 *caps = data; > + u32 diff = *caps ^ val; > + u32 allowed = MMC_CAP_AGGRESSIVE_PM | > + MMC_CAP_SD_HIGHSPEED | > + MMC_CAP_MMC_HIGHSPEED | > + MMC_CAP_UHS | > + MMC_CAP_DDR; > + > + if (diff & ~allowed) > + return -EINVAL; > + > + *caps = val; > + > + return 0; > +} > + > +static int mmc_caps2_set(void *data, u64 val) > +{ > + u32 allowed = MMC_CAP2_HSX00_1_8V | MMC_CAP2_HSX00_1_2V; > + u32 *caps = data; > + u32 diff = *caps ^ val; > + > + if (diff & ~allowed) > + return -EINVAL; > + > + *caps = val; > + > + return 0; > +} > + > +DEFINE_DEBUGFS_ATTRIBUTE(mmc_caps_fops, mmc_caps_get, mmc_caps_set, > + "0x%08llx\n"); > +DEFINE_DEBUGFS_ATTRIBUTE(mmc_caps2_fops, mmc_caps_get, mmc_caps2_set, > + "0x%08llx\n"); > + > void mmc_add_host_debugfs(struct mmc_host *host) > { > struct dentry *root; > @@ -306,8 +352,9 @@ void mmc_add_host_debugfs(struct mmc_host *host) > host->debugfs_root = root; > > debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops); > - debugfs_create_x32("caps", S_IRUSR, root, &host->caps); > - debugfs_create_x32("caps2", S_IRUSR, root, &host->caps2); > + debugfs_create_file("caps", 0600, root, &host->caps, &mmc_caps_fops); > + debugfs_create_file("caps2", 0600, root, &host->caps2, > + &mmc_caps2_fops); Would it be better to use "S_IRUSR | S_IWUSR" instead of "0600"? > debugfs_create_file_unsafe("clock", S_IRUSR | S_IWUSR, root, host, > &mmc_clock_fops); > > > -- > 2.34.1 >