On Thu, 23 Jun 2022 at 10:00, 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. > > To make changing the modes easier, allow the various host controller > capabilities to be cleared via a module parameter. (A per-controller > debugfs wouldn't work since the controller needs to be re-probed to > trigger re-init of cards. A module parameter is used instead of a I think we could make use of a per-controller debugfs thing, if used in combination with MMC_CAP_AGGRESSIVE_PM and runtime PM. As runtime PM also has sysfs interface for each device, we can control runtime PM for the card's device (to trigger re-initialization of the card). In between runtime suspend/resume of the card's device, we should be able to change the supported speed modes, through debug fs. Would this work for you? Kind regards Uffe > global debugfs to allow this to be also set via the kernel command > line.) > > 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 > indented use case. A warning is emitted when the caps clearing is in > effect. > > Example of use: > > # grep timing /sys/kernel/debug/mmc0/ios > timing spec: 9 (mmc HS200) > > // MMC_CAP2_HS200_1_8V_SDR > # echo $((1 << 5)) > /sys/module/mmc_core/parameters/caps2_clear > > # echo 16d40000.mmc > /sys/bus/platform/drivers/dwmmc_exynos/unbind > # echo 16d40000.mmc > /sys/bus/platform/drivers/dwmmc_exynos/bind > # grep timing /sys/kernel/debug/mmc0/ios > timing spec: 8 (mmc DDR52) > > // MMC_CAP_1_8V_DDR > # echo $((1 << 12)) > /sys/module/mmc_core/parameters/caps_clear > > # echo 16d40000.mmc > /sys/bus/platform/drivers/dwmmc_exynos/unbind > # echo 16d40000.mmc > /sys/bus/platform/drivers/dwmmc_exynos/bind > # grep timing /sys/kernel/debug/mmc0/ios > timing spec: 1 (mmc high-speed) > > # echo 0 > /sys/module/mmc_core/parameters/caps2_clear > > # echo 16d40000.mmc > /sys/bus/platform/drivers/dwmmc_exynos/unbind > # echo 16d40000.mmc > /sys/bus/platform/drivers/dwmmc_exynos/bind > # grep timing /sys/kernel/debug/mmc0/ios > timing spec: 9 (mmc HS200) > > Signed-off-by: Vincent Whitchurch <vincent.whitchurch@xxxxxxxx> > --- > drivers/mmc/core/host.c | 12 ++++++++++++ > 1 file changed, 12 insertions(+) > > diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c > index 2ed2b4d5e5a5..37971b7c7f62 100644 > --- a/drivers/mmc/core/host.c > +++ b/drivers/mmc/core/host.c > @@ -34,6 +34,10 @@ > #define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev) > > static DEFINE_IDA(mmc_host_ida); > +static unsigned int caps_clear, caps2_clear; > + > +module_param(caps_clear, uint, 0644); > +module_param(caps2_clear, uint, 0644); > > #ifdef CONFIG_PM_SLEEP > static int mmc_host_class_prepare(struct device *dev) > @@ -411,6 +415,14 @@ int mmc_of_parse(struct mmc_host *host) > host->caps2 &= ~(MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V | > MMC_CAP2_HS400_ES); > > + if (caps_clear || caps2_clear) > + dev_warn(host->parent, > + "clearing host controller caps %#x caps2 %#x\n", > + caps_clear, caps2_clear); > + > + host->caps &= ~caps_clear; > + host->caps2 &= ~caps2_clear; > + > /* Must be after "non-removable" check */ > if (device_property_read_u32(dev, "fixed-emmc-driver-type", &drv_type) == 0) { > if (host->caps & MMC_CAP_NONREMOVABLE) > -- > 2.34.1 >