diff mbox series

[2/2] mmc: pwrseq_simple: add support for reset control

Message ID 20241004120740.2887776-2-catalin.popescu@leica-geosystems.com (mailing list archive)
State New
Headers show
Series [1/2] dt-bindings: mmc: mmc-pwrseq-simple: add support for reset control | expand

Commit Message

Catalin Popescu Oct. 4, 2024, 12:07 p.m. UTC
Reset controls are refcounted and as such allows to use shared resets or
gpios across drivers. Add support for reset control while keeping in
place the support for gpios. Use compatible string to choose between
reset control ("mmc-pwrseq-simple-reset") and reset gpios
("mmc-pwrseq-simple"). Only one reset control is supported.

Signed-off-by: Catalin Popescu <catalin.popescu@leica-geosystems.com>
---
 drivers/mmc/core/pwrseq_simple.c | 58 ++++++++++++++++++++++++++------
 1 file changed, 48 insertions(+), 10 deletions(-)

Comments

kernel test robot Oct. 5, 2024, 2:19 p.m. UTC | #1
Hi Catalin,

kernel test robot noticed the following build warnings:

[auto build test WARNING on robh/for-next]
[also build test WARNING on linus/master v6.12-rc1 next-20241004]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Catalin-Popescu/mmc-pwrseq_simple-add-support-for-reset-control/20241004-200909
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link:    https://lore.kernel.org/r/20241004120740.2887776-2-catalin.popescu%40leica-geosystems.com
patch subject: [PATCH 2/2] mmc: pwrseq_simple: add support for reset control
config: x86_64-randconfig-123-20241005 (https://download.01.org/0day-ci/archive/20241005/202410052201.xEk9eC0T-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241005/202410052201.xEk9eC0T-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410052201.xEk9eC0T-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/mmc/core/pwrseq_simple.c:123:31: sparse: sparse: symbol 'mmc_pwrseq_simple_gpio' was not declared. Should it be static?
>> drivers/mmc/core/pwrseq_simple.c:127:31: sparse: sparse: symbol 'mmc_pwrseq_simple_reset' was not declared. Should it be static?

vim +/mmc_pwrseq_simple_gpio +123 drivers/mmc/core/pwrseq_simple.c

   122	
 > 123	struct mmc_pwrseq_simple_data mmc_pwrseq_simple_gpio = {
   124		.use_reset = false,
   125	};
   126	
 > 127	struct mmc_pwrseq_simple_data mmc_pwrseq_simple_reset = {
   128		.use_reset = true,
   129	};
   130
diff mbox series

Patch

diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c
index 9e016b0746f5..6495b97d48d9 100644
--- a/drivers/mmc/core/pwrseq_simple.c
+++ b/drivers/mmc/core/pwrseq_simple.c
@@ -17,11 +17,17 @@ 
 #include <linux/gpio/consumer.h>
 #include <linux/delay.h>
 #include <linux/property.h>
+#include <linux/of.h>
+#include <linux/reset.h>
 
 #include <linux/mmc/host.h>
 
 #include "pwrseq.h"
 
+struct mmc_pwrseq_simple_data {
+	bool use_reset;
+};
+
 struct mmc_pwrseq_simple {
 	struct mmc_pwrseq pwrseq;
 	bool clk_enabled;
@@ -29,6 +35,8 @@  struct mmc_pwrseq_simple {
 	u32 power_off_delay_us;
 	struct clk *ext_clk;
 	struct gpio_descs *reset_gpios;
+	struct reset_control *reset_ctrl;
+	const struct mmc_pwrseq_simple_data *data;
 };
 
 #define to_pwrseq_simple(p) container_of(p, struct mmc_pwrseq_simple, pwrseq)
@@ -67,14 +75,21 @@  static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host)
 		pwrseq->clk_enabled = true;
 	}
 
-	mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
+	if (pwrseq->data->use_reset) {
+		reset_control_deassert(pwrseq->reset_ctrl);
+		reset_control_assert(pwrseq->reset_ctrl);
+	} else
+		mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
 }
 
 static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host)
 {
 	struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);
 
-	mmc_pwrseq_simple_set_gpios_value(pwrseq, 0);
+	if (pwrseq->data->use_reset)
+		reset_control_deassert(pwrseq->reset_ctrl);
+	else
+		mmc_pwrseq_simple_set_gpios_value(pwrseq, 0);
 
 	if (pwrseq->post_power_on_delay_ms)
 		msleep(pwrseq->post_power_on_delay_ms);
@@ -84,7 +99,10 @@  static void mmc_pwrseq_simple_power_off(struct mmc_host *host)
 {
 	struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);
 
-	mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
+	if (pwrseq->data->use_reset)
+		reset_control_assert(pwrseq->reset_ctrl);
+	else
+		mmc_pwrseq_simple_set_gpios_value(pwrseq, 1);
 
 	if (pwrseq->power_off_delay_us)
 		usleep_range(pwrseq->power_off_delay_us,
@@ -102,8 +120,17 @@  static const struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = {
 	.power_off = mmc_pwrseq_simple_power_off,
 };
 
+struct mmc_pwrseq_simple_data mmc_pwrseq_simple_gpio = {
+	.use_reset = false,
+};
+
+struct mmc_pwrseq_simple_data mmc_pwrseq_simple_reset = {
+	.use_reset = true,
+};
+
 static const struct of_device_id mmc_pwrseq_simple_of_match[] = {
-	{ .compatible = "mmc-pwrseq-simple",},
+	{ .compatible = "mmc-pwrseq-simple", .data = &mmc_pwrseq_simple_gpio },
+	{ .compatible = "mmc-pwrseq-simple-reset", .data = &mmc_pwrseq_simple_reset },
 	{/* sentinel */},
 };
 MODULE_DEVICE_TABLE(of, mmc_pwrseq_simple_of_match);
@@ -121,12 +148,23 @@  static int mmc_pwrseq_simple_probe(struct platform_device *pdev)
 	if (IS_ERR(pwrseq->ext_clk) && PTR_ERR(pwrseq->ext_clk) != -ENOENT)
 		return dev_err_probe(dev, PTR_ERR(pwrseq->ext_clk), "external clock not ready\n");
 
-	pwrseq->reset_gpios = devm_gpiod_get_array(dev, "reset",
-							GPIOD_OUT_HIGH);
-	if (IS_ERR(pwrseq->reset_gpios) &&
-	    PTR_ERR(pwrseq->reset_gpios) != -ENOENT &&
-	    PTR_ERR(pwrseq->reset_gpios) != -ENOSYS) {
-		return dev_err_probe(dev, PTR_ERR(pwrseq->reset_gpios), "reset GPIOs not ready\n");
+	pwrseq->data = of_device_get_match_data(dev);
+	if (!pwrseq->data)
+		return -EINVAL;
+
+	if (pwrseq->data->use_reset) {
+		pwrseq->reset_ctrl = devm_reset_control_get_optional_shared(dev, NULL);
+		if (IS_ERR(pwrseq->reset_ctrl))
+			return dev_err_probe(dev, PTR_ERR(pwrseq->reset_ctrl),
+					     "reset controls not ready\n");
+	} else {
+		pwrseq->reset_gpios = devm_gpiod_get_array(dev, "reset", GPIOD_OUT_HIGH);
+		if (IS_ERR(pwrseq->reset_gpios) &&
+		    PTR_ERR(pwrseq->reset_gpios) != -ENOENT &&
+		    PTR_ERR(pwrseq->reset_gpios) != -ENOSYS) {
+			return dev_err_probe(dev, PTR_ERR(pwrseq->reset_gpios),
+					     "reset GPIOs not ready\n");
+		}
 	}
 
 	device_property_read_u32(dev, "post-power-on-delay-ms",