diff options
Diffstat (limited to 'drivers/rtc/rtc-snvs.c')
| -rw-r--r-- | drivers/rtc/rtc-snvs.c | 39 | 
1 files changed, 36 insertions, 3 deletions
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index fa384fe28988..2cd8ffe5c698 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c @@ -17,6 +17,7 @@  #include <linux/of_device.h>  #include <linux/platform_device.h>  #include <linux/rtc.h> +#include <linux/clk.h>  /* These register offsets are relative to LP (Low Power) range */  #define SNVS_LPCR		0x04 @@ -39,6 +40,7 @@ struct snvs_rtc_data {  	void __iomem *ioaddr;  	int irq;  	spinlock_t lock; +	struct clk *clk;  };  static u32 rtc_read_lp_counter(void __iomem *ioaddr) @@ -260,6 +262,18 @@ static int snvs_rtc_probe(struct platform_device *pdev)  	if (data->irq < 0)  		return data->irq; +	data->clk = devm_clk_get(&pdev->dev, "snvs-rtc"); +	if (IS_ERR(data->clk)) { +		data->clk = NULL; +	} else { +		ret = clk_prepare_enable(data->clk); +		if (ret) { +			dev_err(&pdev->dev, +				"Could not prepare or enable the snvs clock\n"); +			return ret; +		} +	} +  	platform_set_drvdata(pdev, data);  	spin_lock_init(&data->lock); @@ -280,7 +294,7 @@ static int snvs_rtc_probe(struct platform_device *pdev)  	if (ret) {  		dev_err(&pdev->dev, "failed to request irq %d: %d\n",  			data->irq, ret); -		return ret; +		goto error_rtc_device_register;  	}  	data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, @@ -288,10 +302,16 @@ static int snvs_rtc_probe(struct platform_device *pdev)  	if (IS_ERR(data->rtc)) {  		ret = PTR_ERR(data->rtc);  		dev_err(&pdev->dev, "failed to register rtc: %d\n", ret); -		return ret; +		goto error_rtc_device_register;  	}  	return 0; + +error_rtc_device_register: +	if (data->clk) +		clk_disable_unprepare(data->clk); + +	return ret;  }  #ifdef CONFIG_PM_SLEEP @@ -302,21 +322,34 @@ static int snvs_rtc_suspend(struct device *dev)  	if (device_may_wakeup(dev))  		enable_irq_wake(data->irq); +	if (data->clk) +		clk_disable_unprepare(data->clk); +  	return 0;  }  static int snvs_rtc_resume(struct device *dev)  {  	struct snvs_rtc_data *data = dev_get_drvdata(dev); +	int ret;  	if (device_may_wakeup(dev))  		disable_irq_wake(data->irq); +	if (data->clk) { +		ret = clk_prepare_enable(data->clk); +		if (ret) +			return ret; +	} +  	return 0;  }  #endif -static SIMPLE_DEV_PM_OPS(snvs_rtc_pm_ops, snvs_rtc_suspend, snvs_rtc_resume); +static const struct dev_pm_ops snvs_rtc_pm_ops = { +	.suspend_noirq = snvs_rtc_suspend, +	.resume_noirq = snvs_rtc_resume, +};  static const struct of_device_id snvs_dt_ids[] = {  	{ .compatible = "fsl,sec-v4.0-mon-rtc-lp", },  |