1
0
Fork 0

rtc: snvs: Add necessary clock operations for RTC APIs

There could be still RTC registers access after RTC suspend
with clock disabled, need to add clock operations for each
RTC API to make sure accessing RTC registers is successfully.

Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Link: https://lore.kernel.org/r/1590113996-31845-2-git-send-email-Anson.Huang@nxp.com
alistair/sunxi64-5.8
Anson Huang 2020-05-22 10:19:56 +08:00 committed by Alexandre Belloni
parent 20af67700b
commit 4b957bde56
1 changed files with 53 additions and 2 deletions

View File

@ -148,10 +148,21 @@ static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm) static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ {
struct snvs_rtc_data *data = dev_get_drvdata(dev); struct snvs_rtc_data *data = dev_get_drvdata(dev);
unsigned long time = rtc_read_lp_counter(data); unsigned long time;
int ret;
if (data->clk) {
ret = clk_enable(data->clk);
if (ret)
return ret;
}
time = rtc_read_lp_counter(data);
rtc_time64_to_tm(time, tm); rtc_time64_to_tm(time, tm);
if (data->clk)
clk_disable(data->clk);
return 0; return 0;
} }
@ -161,6 +172,12 @@ static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
unsigned long time = rtc_tm_to_time64(tm); unsigned long time = rtc_tm_to_time64(tm);
int ret; int ret;
if (data->clk) {
ret = clk_enable(data->clk);
if (ret)
return ret;
}
/* Disable RTC first */ /* Disable RTC first */
ret = snvs_rtc_enable(data, false); ret = snvs_rtc_enable(data, false);
if (ret) if (ret)
@ -173,6 +190,9 @@ static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
/* Enable RTC again */ /* Enable RTC again */
ret = snvs_rtc_enable(data, true); ret = snvs_rtc_enable(data, true);
if (data->clk)
clk_disable(data->clk);
return ret; return ret;
} }
@ -180,6 +200,13 @@ static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{ {
struct snvs_rtc_data *data = dev_get_drvdata(dev); struct snvs_rtc_data *data = dev_get_drvdata(dev);
u32 lptar, lpsr; u32 lptar, lpsr;
int ret;
if (data->clk) {
ret = clk_enable(data->clk);
if (ret)
return ret;
}
regmap_read(data->regmap, data->offset + SNVS_LPTAR, &lptar); regmap_read(data->regmap, data->offset + SNVS_LPTAR, &lptar);
rtc_time64_to_tm(lptar, &alrm->time); rtc_time64_to_tm(lptar, &alrm->time);
@ -187,18 +214,33 @@ static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr); regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr);
alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0; alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0;
if (data->clk)
clk_disable(data->clk);
return 0; return 0;
} }
static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
{ {
struct snvs_rtc_data *data = dev_get_drvdata(dev); struct snvs_rtc_data *data = dev_get_drvdata(dev);
int ret;
if (data->clk) {
ret = clk_enable(data->clk);
if (ret)
return ret;
}
regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, regmap_update_bits(data->regmap, data->offset + SNVS_LPCR,
(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN), (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN),
enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0); enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0);
return rtc_write_sync_lp(data); ret = rtc_write_sync_lp(data);
if (data->clk)
clk_disable(data->clk);
return ret;
} }
static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
@ -207,6 +249,12 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
unsigned long time = rtc_tm_to_time64(&alrm->time); unsigned long time = rtc_tm_to_time64(&alrm->time);
int ret; int ret;
if (data->clk) {
ret = clk_enable(data->clk);
if (ret)
return ret;
}
regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0); regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0);
ret = rtc_write_sync_lp(data); ret = rtc_write_sync_lp(data);
if (ret) if (ret)
@ -216,6 +264,9 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
/* Clear alarm interrupt status bit */ /* Clear alarm interrupt status bit */
regmap_write(data->regmap, data->offset + SNVS_LPSR, SNVS_LPSR_LPTA); regmap_write(data->regmap, data->offset + SNVS_LPSR, SNVS_LPSR_LPTA);
if (data->clk)
clk_disable(data->clk);
return snvs_rtc_alarm_irq_enable(dev, alrm->enabled); return snvs_rtc_alarm_irq_enable(dev, alrm->enabled);
} }