diff options
Diffstat (limited to 'drivers/mmc/core/pwrseq_simple.c')
| -rw-r--r-- | drivers/mmc/core/pwrseq_simple.c | 91 | 
1 files changed, 49 insertions, 42 deletions
diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c index bc173e18b71c..450d907c6e6c 100644 --- a/drivers/mmc/core/pwrseq_simple.c +++ b/drivers/mmc/core/pwrseq_simple.c @@ -8,7 +8,10 @@   *  Simple MMC power sequence management   */  #include <linux/clk.h> +#include <linux/init.h>  #include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/module.h>  #include <linux/slab.h>  #include <linux/device.h>  #include <linux/err.h> @@ -25,6 +28,8 @@ struct mmc_pwrseq_simple {  	struct gpio_descs *reset_gpios;  }; +#define to_pwrseq_simple(p) container_of(p, struct mmc_pwrseq_simple, pwrseq) +  static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq,  					      int value)  { @@ -44,8 +49,7 @@ static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq,  static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host)  { -	struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, -					struct mmc_pwrseq_simple, pwrseq); +	struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);  	if (!IS_ERR(pwrseq->ext_clk) && !pwrseq->clk_enabled) {  		clk_prepare_enable(pwrseq->ext_clk); @@ -57,16 +61,14 @@ static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host)  static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host)  { -	struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, -					struct mmc_pwrseq_simple, pwrseq); +	struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);  	mmc_pwrseq_simple_set_gpios_value(pwrseq, 0);  }  static void mmc_pwrseq_simple_power_off(struct mmc_host *host)  { -	struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, -					struct mmc_pwrseq_simple, pwrseq); +	struct mmc_pwrseq_simple *pwrseq = to_pwrseq_simple(host->pwrseq);  	mmc_pwrseq_simple_set_gpios_value(pwrseq, 1); @@ -76,59 +78,64 @@ static void mmc_pwrseq_simple_power_off(struct mmc_host *host)  	}  } -static void mmc_pwrseq_simple_free(struct mmc_host *host) -{ -	struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, -					struct mmc_pwrseq_simple, pwrseq); - -	if (!IS_ERR(pwrseq->reset_gpios)) -		gpiod_put_array(pwrseq->reset_gpios); - -	if (!IS_ERR(pwrseq->ext_clk)) -		clk_put(pwrseq->ext_clk); - -	kfree(pwrseq); -} -  static const struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = {  	.pre_power_on = mmc_pwrseq_simple_pre_power_on,  	.post_power_on = mmc_pwrseq_simple_post_power_on,  	.power_off = mmc_pwrseq_simple_power_off, -	.free = mmc_pwrseq_simple_free,  }; -struct mmc_pwrseq *mmc_pwrseq_simple_alloc(struct mmc_host *host, -					   struct device *dev) +static const struct of_device_id mmc_pwrseq_simple_of_match[] = { +	{ .compatible = "mmc-pwrseq-simple",}, +	{/* sentinel */}, +}; +MODULE_DEVICE_TABLE(of, mmc_pwrseq_simple_of_match); + +static int mmc_pwrseq_simple_probe(struct platform_device *pdev)  {  	struct mmc_pwrseq_simple *pwrseq; -	int ret = 0; +	struct device *dev = &pdev->dev; -	pwrseq = kzalloc(sizeof(*pwrseq), GFP_KERNEL); +	pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL);  	if (!pwrseq) -		return ERR_PTR(-ENOMEM); +		return -ENOMEM; -	pwrseq->ext_clk = clk_get(dev, "ext_clock"); -	if (IS_ERR(pwrseq->ext_clk) && -	    PTR_ERR(pwrseq->ext_clk) != -ENOENT) { -		ret = PTR_ERR(pwrseq->ext_clk); -		goto free; -	} +	pwrseq->ext_clk = devm_clk_get(dev, "ext_clock"); +	if (IS_ERR(pwrseq->ext_clk) && PTR_ERR(pwrseq->ext_clk) != -ENOENT) +		return PTR_ERR(pwrseq->ext_clk); -	pwrseq->reset_gpios = gpiod_get_array(dev, "reset", GPIOD_OUT_HIGH); +	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) { -		ret = PTR_ERR(pwrseq->reset_gpios); -		goto clk_put; +		return PTR_ERR(pwrseq->reset_gpios);  	} +	pwrseq->pwrseq.dev = dev;  	pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops; +	pwrseq->pwrseq.owner = THIS_MODULE; +	platform_set_drvdata(pdev, pwrseq); -	return &pwrseq->pwrseq; -clk_put: -	if (!IS_ERR(pwrseq->ext_clk)) -		clk_put(pwrseq->ext_clk); -free: -	kfree(pwrseq); -	return ERR_PTR(ret); +	return mmc_pwrseq_register(&pwrseq->pwrseq);  } + +static int mmc_pwrseq_simple_remove(struct platform_device *pdev) +{ +	struct mmc_pwrseq_simple *pwrseq = platform_get_drvdata(pdev); + +	mmc_pwrseq_unregister(&pwrseq->pwrseq); + +	return 0; +} + +static struct platform_driver mmc_pwrseq_simple_driver = { +	.probe = mmc_pwrseq_simple_probe, +	.remove = mmc_pwrseq_simple_remove, +	.driver = { +		.name = "pwrseq_simple", +		.of_match_table = mmc_pwrseq_simple_of_match, +	}, +}; + +module_platform_driver(mmc_pwrseq_simple_driver); +MODULE_LICENSE("GPL v2");  | 
