1*07869941SNobuhiro Iwamatsu // SPDX-License-Identifier: GPL-2.0
2495bbde5SBaolin Wang /*
3495bbde5SBaolin Wang * Copyright (C) 2017 Spreadtrum Communications Inc.
4495bbde5SBaolin Wang *
5495bbde5SBaolin Wang */
6495bbde5SBaolin Wang
7495bbde5SBaolin Wang #include <linux/bitops.h>
8495bbde5SBaolin Wang #include <linux/delay.h>
9495bbde5SBaolin Wang #include <linux/err.h>
10495bbde5SBaolin Wang #include <linux/module.h>
11495bbde5SBaolin Wang #include <linux/of.h>
12495bbde5SBaolin Wang #include <linux/platform_device.h>
13495bbde5SBaolin Wang #include <linux/regmap.h>
14495bbde5SBaolin Wang #include <linux/rtc.h>
15495bbde5SBaolin Wang
16495bbde5SBaolin Wang #define SPRD_RTC_SEC_CNT_VALUE 0x0
17495bbde5SBaolin Wang #define SPRD_RTC_MIN_CNT_VALUE 0x4
18495bbde5SBaolin Wang #define SPRD_RTC_HOUR_CNT_VALUE 0x8
19495bbde5SBaolin Wang #define SPRD_RTC_DAY_CNT_VALUE 0xc
20495bbde5SBaolin Wang #define SPRD_RTC_SEC_CNT_UPD 0x10
21495bbde5SBaolin Wang #define SPRD_RTC_MIN_CNT_UPD 0x14
22495bbde5SBaolin Wang #define SPRD_RTC_HOUR_CNT_UPD 0x18
23495bbde5SBaolin Wang #define SPRD_RTC_DAY_CNT_UPD 0x1c
24495bbde5SBaolin Wang #define SPRD_RTC_SEC_ALM_UPD 0x20
25495bbde5SBaolin Wang #define SPRD_RTC_MIN_ALM_UPD 0x24
26495bbde5SBaolin Wang #define SPRD_RTC_HOUR_ALM_UPD 0x28
27495bbde5SBaolin Wang #define SPRD_RTC_DAY_ALM_UPD 0x2c
28495bbde5SBaolin Wang #define SPRD_RTC_INT_EN 0x30
29495bbde5SBaolin Wang #define SPRD_RTC_INT_RAW_STS 0x34
30495bbde5SBaolin Wang #define SPRD_RTC_INT_CLR 0x38
31495bbde5SBaolin Wang #define SPRD_RTC_INT_MASK_STS 0x3C
32495bbde5SBaolin Wang #define SPRD_RTC_SEC_ALM_VALUE 0x40
33495bbde5SBaolin Wang #define SPRD_RTC_MIN_ALM_VALUE 0x44
34495bbde5SBaolin Wang #define SPRD_RTC_HOUR_ALM_VALUE 0x48
35495bbde5SBaolin Wang #define SPRD_RTC_DAY_ALM_VALUE 0x4c
36495bbde5SBaolin Wang #define SPRD_RTC_SPG_VALUE 0x50
37495bbde5SBaolin Wang #define SPRD_RTC_SPG_UPD 0x54
38a0defd7cSBaolin Wang #define SPRD_RTC_PWR_CTRL 0x58
39a0defd7cSBaolin Wang #define SPRD_RTC_PWR_STS 0x5c
40495bbde5SBaolin Wang #define SPRD_RTC_SEC_AUXALM_UPD 0x60
41495bbde5SBaolin Wang #define SPRD_RTC_MIN_AUXALM_UPD 0x64
42495bbde5SBaolin Wang #define SPRD_RTC_HOUR_AUXALM_UPD 0x68
43495bbde5SBaolin Wang #define SPRD_RTC_DAY_AUXALM_UPD 0x6c
44495bbde5SBaolin Wang
45495bbde5SBaolin Wang /* BIT & MASK definition for SPRD_RTC_INT_* registers */
46495bbde5SBaolin Wang #define SPRD_RTC_SEC_EN BIT(0)
47495bbde5SBaolin Wang #define SPRD_RTC_MIN_EN BIT(1)
48495bbde5SBaolin Wang #define SPRD_RTC_HOUR_EN BIT(2)
49495bbde5SBaolin Wang #define SPRD_RTC_DAY_EN BIT(3)
50495bbde5SBaolin Wang #define SPRD_RTC_ALARM_EN BIT(4)
51495bbde5SBaolin Wang #define SPRD_RTC_HRS_FORMAT_EN BIT(5)
52495bbde5SBaolin Wang #define SPRD_RTC_AUXALM_EN BIT(6)
53495bbde5SBaolin Wang #define SPRD_RTC_SPG_UPD_EN BIT(7)
54495bbde5SBaolin Wang #define SPRD_RTC_SEC_UPD_EN BIT(8)
55495bbde5SBaolin Wang #define SPRD_RTC_MIN_UPD_EN BIT(9)
56495bbde5SBaolin Wang #define SPRD_RTC_HOUR_UPD_EN BIT(10)
57495bbde5SBaolin Wang #define SPRD_RTC_DAY_UPD_EN BIT(11)
58495bbde5SBaolin Wang #define SPRD_RTC_ALMSEC_UPD_EN BIT(12)
59495bbde5SBaolin Wang #define SPRD_RTC_ALMMIN_UPD_EN BIT(13)
60495bbde5SBaolin Wang #define SPRD_RTC_ALMHOUR_UPD_EN BIT(14)
61495bbde5SBaolin Wang #define SPRD_RTC_ALMDAY_UPD_EN BIT(15)
62495bbde5SBaolin Wang #define SPRD_RTC_INT_MASK GENMASK(15, 0)
63495bbde5SBaolin Wang
64495bbde5SBaolin Wang #define SPRD_RTC_TIME_INT_MASK \
65495bbde5SBaolin Wang (SPRD_RTC_SEC_UPD_EN | SPRD_RTC_MIN_UPD_EN | \
66495bbde5SBaolin Wang SPRD_RTC_HOUR_UPD_EN | SPRD_RTC_DAY_UPD_EN)
67495bbde5SBaolin Wang
68495bbde5SBaolin Wang #define SPRD_RTC_ALMTIME_INT_MASK \
69495bbde5SBaolin Wang (SPRD_RTC_ALMSEC_UPD_EN | SPRD_RTC_ALMMIN_UPD_EN | \
70495bbde5SBaolin Wang SPRD_RTC_ALMHOUR_UPD_EN | SPRD_RTC_ALMDAY_UPD_EN)
71495bbde5SBaolin Wang
72495bbde5SBaolin Wang #define SPRD_RTC_ALM_INT_MASK \
73495bbde5SBaolin Wang (SPRD_RTC_SEC_EN | SPRD_RTC_MIN_EN | \
74495bbde5SBaolin Wang SPRD_RTC_HOUR_EN | SPRD_RTC_DAY_EN | \
75495bbde5SBaolin Wang SPRD_RTC_ALARM_EN | SPRD_RTC_AUXALM_EN)
76495bbde5SBaolin Wang
77495bbde5SBaolin Wang /* second/minute/hour/day values mask definition */
78495bbde5SBaolin Wang #define SPRD_RTC_SEC_MASK GENMASK(5, 0)
79495bbde5SBaolin Wang #define SPRD_RTC_MIN_MASK GENMASK(5, 0)
80495bbde5SBaolin Wang #define SPRD_RTC_HOUR_MASK GENMASK(4, 0)
81495bbde5SBaolin Wang #define SPRD_RTC_DAY_MASK GENMASK(15, 0)
82495bbde5SBaolin Wang
83495bbde5SBaolin Wang /* alarm lock definition for SPRD_RTC_SPG_UPD register */
84495bbde5SBaolin Wang #define SPRD_RTC_ALMLOCK_MASK GENMASK(7, 0)
85495bbde5SBaolin Wang #define SPRD_RTC_ALM_UNLOCK 0xa5
86495bbde5SBaolin Wang #define SPRD_RTC_ALM_LOCK (~SPRD_RTC_ALM_UNLOCK & \
87495bbde5SBaolin Wang SPRD_RTC_ALMLOCK_MASK)
88495bbde5SBaolin Wang
89495bbde5SBaolin Wang /* SPG values definition for SPRD_RTC_SPG_UPD register */
90495bbde5SBaolin Wang #define SPRD_RTC_POWEROFF_ALM_FLAG BIT(8)
91a0defd7cSBaolin Wang
92a0defd7cSBaolin Wang /* power control/status definition */
93a0defd7cSBaolin Wang #define SPRD_RTC_POWER_RESET_VALUE 0x96
94a0defd7cSBaolin Wang #define SPRD_RTC_POWER_STS_CLEAR GENMASK(7, 0)
95a0defd7cSBaolin Wang #define SPRD_RTC_POWER_STS_SHIFT 8
96a0defd7cSBaolin Wang #define SPRD_RTC_POWER_STS_VALID \
97a0defd7cSBaolin Wang (~SPRD_RTC_POWER_RESET_VALUE << SPRD_RTC_POWER_STS_SHIFT)
98495bbde5SBaolin Wang
99495bbde5SBaolin Wang /* timeout of synchronizing time and alarm registers (us) */
100495bbde5SBaolin Wang #define SPRD_RTC_POLL_TIMEOUT 200000
101495bbde5SBaolin Wang #define SPRD_RTC_POLL_DELAY_US 20000
102495bbde5SBaolin Wang
103495bbde5SBaolin Wang struct sprd_rtc {
104495bbde5SBaolin Wang struct rtc_device *rtc;
105495bbde5SBaolin Wang struct regmap *regmap;
106495bbde5SBaolin Wang struct device *dev;
107495bbde5SBaolin Wang u32 base;
108495bbde5SBaolin Wang int irq;
109495bbde5SBaolin Wang bool valid;
110495bbde5SBaolin Wang };
111495bbde5SBaolin Wang
112495bbde5SBaolin Wang /*
113495bbde5SBaolin Wang * The Spreadtrum RTC controller has 3 groups registers, including time, normal
114495bbde5SBaolin Wang * alarm and auxiliary alarm. The time group registers are used to set RTC time,
115495bbde5SBaolin Wang * the normal alarm registers are used to set normal alarm, and the auxiliary
116495bbde5SBaolin Wang * alarm registers are used to set auxiliary alarm. Both alarm event and
117495bbde5SBaolin Wang * auxiliary alarm event can wake up system from deep sleep, but only alarm
118495bbde5SBaolin Wang * event can power up system from power down status.
119495bbde5SBaolin Wang */
120495bbde5SBaolin Wang enum sprd_rtc_reg_types {
121495bbde5SBaolin Wang SPRD_RTC_TIME,
122495bbde5SBaolin Wang SPRD_RTC_ALARM,
123495bbde5SBaolin Wang SPRD_RTC_AUX_ALARM,
124495bbde5SBaolin Wang };
125495bbde5SBaolin Wang
sprd_rtc_clear_alarm_ints(struct sprd_rtc * rtc)126495bbde5SBaolin Wang static int sprd_rtc_clear_alarm_ints(struct sprd_rtc *rtc)
127495bbde5SBaolin Wang {
128495bbde5SBaolin Wang return regmap_write(rtc->regmap, rtc->base + SPRD_RTC_INT_CLR,
129495bbde5SBaolin Wang SPRD_RTC_ALM_INT_MASK);
130495bbde5SBaolin Wang }
131495bbde5SBaolin Wang
sprd_rtc_lock_alarm(struct sprd_rtc * rtc,bool lock)132495bbde5SBaolin Wang static int sprd_rtc_lock_alarm(struct sprd_rtc *rtc, bool lock)
133495bbde5SBaolin Wang {
134495bbde5SBaolin Wang int ret;
135495bbde5SBaolin Wang u32 val;
136495bbde5SBaolin Wang
137495bbde5SBaolin Wang ret = regmap_read(rtc->regmap, rtc->base + SPRD_RTC_SPG_VALUE, &val);
138495bbde5SBaolin Wang if (ret)
139495bbde5SBaolin Wang return ret;
140495bbde5SBaolin Wang
141e02e3ddaSBaolin Wang val &= ~SPRD_RTC_ALMLOCK_MASK;
142495bbde5SBaolin Wang if (lock)
143495bbde5SBaolin Wang val |= SPRD_RTC_ALM_LOCK;
144495bbde5SBaolin Wang else
145495bbde5SBaolin Wang val |= SPRD_RTC_ALM_UNLOCK | SPRD_RTC_POWEROFF_ALM_FLAG;
146495bbde5SBaolin Wang
147495bbde5SBaolin Wang ret = regmap_write(rtc->regmap, rtc->base + SPRD_RTC_SPG_UPD, val);
148495bbde5SBaolin Wang if (ret)
149495bbde5SBaolin Wang return ret;
150495bbde5SBaolin Wang
151495bbde5SBaolin Wang /* wait until the SPG value is updated successfully */
152495bbde5SBaolin Wang ret = regmap_read_poll_timeout(rtc->regmap,
153495bbde5SBaolin Wang rtc->base + SPRD_RTC_INT_RAW_STS, val,
154495bbde5SBaolin Wang (val & SPRD_RTC_SPG_UPD_EN),
155495bbde5SBaolin Wang SPRD_RTC_POLL_DELAY_US,
156495bbde5SBaolin Wang SPRD_RTC_POLL_TIMEOUT);
157495bbde5SBaolin Wang if (ret) {
158495bbde5SBaolin Wang dev_err(rtc->dev, "failed to update SPG value:%d\n", ret);
159495bbde5SBaolin Wang return ret;
160495bbde5SBaolin Wang }
161495bbde5SBaolin Wang
1627db5adfaSBaolin Wang return regmap_write(rtc->regmap, rtc->base + SPRD_RTC_INT_CLR,
1637db5adfaSBaolin Wang SPRD_RTC_SPG_UPD_EN);
164495bbde5SBaolin Wang }
165495bbde5SBaolin Wang
sprd_rtc_get_secs(struct sprd_rtc * rtc,enum sprd_rtc_reg_types type,time64_t * secs)166495bbde5SBaolin Wang static int sprd_rtc_get_secs(struct sprd_rtc *rtc, enum sprd_rtc_reg_types type,
167495bbde5SBaolin Wang time64_t *secs)
168495bbde5SBaolin Wang {
169495bbde5SBaolin Wang u32 sec_reg, min_reg, hour_reg, day_reg;
170495bbde5SBaolin Wang u32 val, sec, min, hour, day;
171495bbde5SBaolin Wang int ret;
172495bbde5SBaolin Wang
173495bbde5SBaolin Wang switch (type) {
174495bbde5SBaolin Wang case SPRD_RTC_TIME:
175495bbde5SBaolin Wang sec_reg = SPRD_RTC_SEC_CNT_VALUE;
176495bbde5SBaolin Wang min_reg = SPRD_RTC_MIN_CNT_VALUE;
177495bbde5SBaolin Wang hour_reg = SPRD_RTC_HOUR_CNT_VALUE;
178495bbde5SBaolin Wang day_reg = SPRD_RTC_DAY_CNT_VALUE;
179495bbde5SBaolin Wang break;
180495bbde5SBaolin Wang case SPRD_RTC_ALARM:
181495bbde5SBaolin Wang sec_reg = SPRD_RTC_SEC_ALM_VALUE;
182495bbde5SBaolin Wang min_reg = SPRD_RTC_MIN_ALM_VALUE;
183495bbde5SBaolin Wang hour_reg = SPRD_RTC_HOUR_ALM_VALUE;
184495bbde5SBaolin Wang day_reg = SPRD_RTC_DAY_ALM_VALUE;
185495bbde5SBaolin Wang break;
186495bbde5SBaolin Wang case SPRD_RTC_AUX_ALARM:
187495bbde5SBaolin Wang sec_reg = SPRD_RTC_SEC_AUXALM_UPD;
188495bbde5SBaolin Wang min_reg = SPRD_RTC_MIN_AUXALM_UPD;
189495bbde5SBaolin Wang hour_reg = SPRD_RTC_HOUR_AUXALM_UPD;
190495bbde5SBaolin Wang day_reg = SPRD_RTC_DAY_AUXALM_UPD;
191495bbde5SBaolin Wang break;
192495bbde5SBaolin Wang default:
193495bbde5SBaolin Wang return -EINVAL;
194495bbde5SBaolin Wang }
195495bbde5SBaolin Wang
196495bbde5SBaolin Wang ret = regmap_read(rtc->regmap, rtc->base + sec_reg, &val);
197495bbde5SBaolin Wang if (ret)
198495bbde5SBaolin Wang return ret;
199495bbde5SBaolin Wang
200495bbde5SBaolin Wang sec = val & SPRD_RTC_SEC_MASK;
201495bbde5SBaolin Wang
202495bbde5SBaolin Wang ret = regmap_read(rtc->regmap, rtc->base + min_reg, &val);
203495bbde5SBaolin Wang if (ret)
204495bbde5SBaolin Wang return ret;
205495bbde5SBaolin Wang
206495bbde5SBaolin Wang min = val & SPRD_RTC_MIN_MASK;
207495bbde5SBaolin Wang
208495bbde5SBaolin Wang ret = regmap_read(rtc->regmap, rtc->base + hour_reg, &val);
209495bbde5SBaolin Wang if (ret)
210495bbde5SBaolin Wang return ret;
211495bbde5SBaolin Wang
212495bbde5SBaolin Wang hour = val & SPRD_RTC_HOUR_MASK;
213495bbde5SBaolin Wang
214495bbde5SBaolin Wang ret = regmap_read(rtc->regmap, rtc->base + day_reg, &val);
215495bbde5SBaolin Wang if (ret)
216495bbde5SBaolin Wang return ret;
217495bbde5SBaolin Wang
218495bbde5SBaolin Wang day = val & SPRD_RTC_DAY_MASK;
219495bbde5SBaolin Wang *secs = (((time64_t)(day * 24) + hour) * 60 + min) * 60 + sec;
220495bbde5SBaolin Wang return 0;
221495bbde5SBaolin Wang }
222495bbde5SBaolin Wang
sprd_rtc_set_secs(struct sprd_rtc * rtc,enum sprd_rtc_reg_types type,time64_t secs)223495bbde5SBaolin Wang static int sprd_rtc_set_secs(struct sprd_rtc *rtc, enum sprd_rtc_reg_types type,
224495bbde5SBaolin Wang time64_t secs)
225495bbde5SBaolin Wang {
226495bbde5SBaolin Wang u32 sec_reg, min_reg, hour_reg, day_reg, sts_mask;
227495bbde5SBaolin Wang u32 sec, min, hour, day, val;
228495bbde5SBaolin Wang int ret, rem;
229495bbde5SBaolin Wang
230495bbde5SBaolin Wang /* convert seconds to RTC time format */
231495bbde5SBaolin Wang day = div_s64_rem(secs, 86400, &rem);
232495bbde5SBaolin Wang hour = rem / 3600;
233495bbde5SBaolin Wang rem -= hour * 3600;
234495bbde5SBaolin Wang min = rem / 60;
235495bbde5SBaolin Wang sec = rem - min * 60;
236495bbde5SBaolin Wang
237495bbde5SBaolin Wang switch (type) {
238495bbde5SBaolin Wang case SPRD_RTC_TIME:
239495bbde5SBaolin Wang sec_reg = SPRD_RTC_SEC_CNT_UPD;
240495bbde5SBaolin Wang min_reg = SPRD_RTC_MIN_CNT_UPD;
241495bbde5SBaolin Wang hour_reg = SPRD_RTC_HOUR_CNT_UPD;
242495bbde5SBaolin Wang day_reg = SPRD_RTC_DAY_CNT_UPD;
243495bbde5SBaolin Wang sts_mask = SPRD_RTC_TIME_INT_MASK;
244495bbde5SBaolin Wang break;
245495bbde5SBaolin Wang case SPRD_RTC_ALARM:
246495bbde5SBaolin Wang sec_reg = SPRD_RTC_SEC_ALM_UPD;
247495bbde5SBaolin Wang min_reg = SPRD_RTC_MIN_ALM_UPD;
248495bbde5SBaolin Wang hour_reg = SPRD_RTC_HOUR_ALM_UPD;
249495bbde5SBaolin Wang day_reg = SPRD_RTC_DAY_ALM_UPD;
250495bbde5SBaolin Wang sts_mask = SPRD_RTC_ALMTIME_INT_MASK;
251495bbde5SBaolin Wang break;
252495bbde5SBaolin Wang case SPRD_RTC_AUX_ALARM:
253495bbde5SBaolin Wang sec_reg = SPRD_RTC_SEC_AUXALM_UPD;
254495bbde5SBaolin Wang min_reg = SPRD_RTC_MIN_AUXALM_UPD;
255495bbde5SBaolin Wang hour_reg = SPRD_RTC_HOUR_AUXALM_UPD;
256495bbde5SBaolin Wang day_reg = SPRD_RTC_DAY_AUXALM_UPD;
257495bbde5SBaolin Wang sts_mask = 0;
258495bbde5SBaolin Wang break;
259495bbde5SBaolin Wang default:
260495bbde5SBaolin Wang return -EINVAL;
261495bbde5SBaolin Wang }
262495bbde5SBaolin Wang
263495bbde5SBaolin Wang ret = regmap_write(rtc->regmap, rtc->base + sec_reg, sec);
264495bbde5SBaolin Wang if (ret)
265495bbde5SBaolin Wang return ret;
266495bbde5SBaolin Wang
267495bbde5SBaolin Wang ret = regmap_write(rtc->regmap, rtc->base + min_reg, min);
268495bbde5SBaolin Wang if (ret)
269495bbde5SBaolin Wang return ret;
270495bbde5SBaolin Wang
271495bbde5SBaolin Wang ret = regmap_write(rtc->regmap, rtc->base + hour_reg, hour);
272495bbde5SBaolin Wang if (ret)
273495bbde5SBaolin Wang return ret;
274495bbde5SBaolin Wang
275495bbde5SBaolin Wang ret = regmap_write(rtc->regmap, rtc->base + day_reg, day);
276495bbde5SBaolin Wang if (ret)
277495bbde5SBaolin Wang return ret;
278495bbde5SBaolin Wang
279495bbde5SBaolin Wang if (type == SPRD_RTC_AUX_ALARM)
280495bbde5SBaolin Wang return 0;
281495bbde5SBaolin Wang
282495bbde5SBaolin Wang /*
283495bbde5SBaolin Wang * Since the time and normal alarm registers are put in always-power-on
284495bbde5SBaolin Wang * region supplied by VDDRTC, then these registers changing time will
285495bbde5SBaolin Wang * be very long, about 125ms. Thus here we should wait until all
286495bbde5SBaolin Wang * values are updated successfully.
287495bbde5SBaolin Wang */
288495bbde5SBaolin Wang ret = regmap_read_poll_timeout(rtc->regmap,
289495bbde5SBaolin Wang rtc->base + SPRD_RTC_INT_RAW_STS, val,
290495bbde5SBaolin Wang ((val & sts_mask) == sts_mask),
291495bbde5SBaolin Wang SPRD_RTC_POLL_DELAY_US,
292495bbde5SBaolin Wang SPRD_RTC_POLL_TIMEOUT);
293495bbde5SBaolin Wang if (ret < 0) {
294495bbde5SBaolin Wang dev_err(rtc->dev, "set time/alarm values timeout\n");
295495bbde5SBaolin Wang return ret;
296495bbde5SBaolin Wang }
297495bbde5SBaolin Wang
298495bbde5SBaolin Wang return regmap_write(rtc->regmap, rtc->base + SPRD_RTC_INT_CLR,
299495bbde5SBaolin Wang sts_mask);
300495bbde5SBaolin Wang }
301495bbde5SBaolin Wang
sprd_rtc_set_aux_alarm(struct device * dev,struct rtc_wkalrm * alrm)302495bbde5SBaolin Wang static int sprd_rtc_set_aux_alarm(struct device *dev, struct rtc_wkalrm *alrm)
303495bbde5SBaolin Wang {
304495bbde5SBaolin Wang struct sprd_rtc *rtc = dev_get_drvdata(dev);
305495bbde5SBaolin Wang time64_t secs = rtc_tm_to_time64(&alrm->time);
306495bbde5SBaolin Wang int ret;
307495bbde5SBaolin Wang
308495bbde5SBaolin Wang /* clear the auxiliary alarm interrupt status */
309495bbde5SBaolin Wang ret = regmap_write(rtc->regmap, rtc->base + SPRD_RTC_INT_CLR,
310495bbde5SBaolin Wang SPRD_RTC_AUXALM_EN);
311495bbde5SBaolin Wang if (ret)
312495bbde5SBaolin Wang return ret;
313495bbde5SBaolin Wang
314495bbde5SBaolin Wang ret = sprd_rtc_set_secs(rtc, SPRD_RTC_AUX_ALARM, secs);
315495bbde5SBaolin Wang if (ret)
316495bbde5SBaolin Wang return ret;
317495bbde5SBaolin Wang
318495bbde5SBaolin Wang if (alrm->enabled) {
319495bbde5SBaolin Wang ret = regmap_update_bits(rtc->regmap,
320495bbde5SBaolin Wang rtc->base + SPRD_RTC_INT_EN,
321495bbde5SBaolin Wang SPRD_RTC_AUXALM_EN,
322495bbde5SBaolin Wang SPRD_RTC_AUXALM_EN);
323495bbde5SBaolin Wang } else {
324495bbde5SBaolin Wang ret = regmap_update_bits(rtc->regmap,
325495bbde5SBaolin Wang rtc->base + SPRD_RTC_INT_EN,
326495bbde5SBaolin Wang SPRD_RTC_AUXALM_EN, 0);
327495bbde5SBaolin Wang }
328495bbde5SBaolin Wang
329495bbde5SBaolin Wang return ret;
330495bbde5SBaolin Wang }
331495bbde5SBaolin Wang
sprd_rtc_read_time(struct device * dev,struct rtc_time * tm)332495bbde5SBaolin Wang static int sprd_rtc_read_time(struct device *dev, struct rtc_time *tm)
333495bbde5SBaolin Wang {
334495bbde5SBaolin Wang struct sprd_rtc *rtc = dev_get_drvdata(dev);
335495bbde5SBaolin Wang time64_t secs;
336495bbde5SBaolin Wang int ret;
337495bbde5SBaolin Wang
338495bbde5SBaolin Wang if (!rtc->valid) {
339495bbde5SBaolin Wang dev_warn(dev, "RTC values are invalid\n");
340495bbde5SBaolin Wang return -EINVAL;
341495bbde5SBaolin Wang }
342495bbde5SBaolin Wang
343495bbde5SBaolin Wang ret = sprd_rtc_get_secs(rtc, SPRD_RTC_TIME, &secs);
344495bbde5SBaolin Wang if (ret)
345495bbde5SBaolin Wang return ret;
346495bbde5SBaolin Wang
347495bbde5SBaolin Wang rtc_time64_to_tm(secs, tm);
34866b32fc5SAlexandre Belloni return 0;
349495bbde5SBaolin Wang }
350495bbde5SBaolin Wang
sprd_rtc_set_time(struct device * dev,struct rtc_time * tm)351495bbde5SBaolin Wang static int sprd_rtc_set_time(struct device *dev, struct rtc_time *tm)
352495bbde5SBaolin Wang {
353495bbde5SBaolin Wang struct sprd_rtc *rtc = dev_get_drvdata(dev);
354495bbde5SBaolin Wang time64_t secs = rtc_tm_to_time64(tm);
355495bbde5SBaolin Wang int ret;
356495bbde5SBaolin Wang
357495bbde5SBaolin Wang ret = sprd_rtc_set_secs(rtc, SPRD_RTC_TIME, secs);
358495bbde5SBaolin Wang if (ret)
359495bbde5SBaolin Wang return ret;
360495bbde5SBaolin Wang
361495bbde5SBaolin Wang if (!rtc->valid) {
362a0defd7cSBaolin Wang /* Clear RTC power status firstly */
363a0defd7cSBaolin Wang ret = regmap_write(rtc->regmap, rtc->base + SPRD_RTC_PWR_CTRL,
364a0defd7cSBaolin Wang SPRD_RTC_POWER_STS_CLEAR);
365495bbde5SBaolin Wang if (ret)
366495bbde5SBaolin Wang return ret;
367495bbde5SBaolin Wang
368a0defd7cSBaolin Wang /*
369a0defd7cSBaolin Wang * Set RTC power status to indicate now RTC has valid time
370a0defd7cSBaolin Wang * values.
371a0defd7cSBaolin Wang */
372a0defd7cSBaolin Wang ret = regmap_write(rtc->regmap, rtc->base + SPRD_RTC_PWR_CTRL,
373a0defd7cSBaolin Wang SPRD_RTC_POWER_STS_VALID);
374a0defd7cSBaolin Wang if (ret)
375495bbde5SBaolin Wang return ret;
376495bbde5SBaolin Wang
377495bbde5SBaolin Wang rtc->valid = true;
378495bbde5SBaolin Wang }
379495bbde5SBaolin Wang
380495bbde5SBaolin Wang return 0;
381495bbde5SBaolin Wang }
382495bbde5SBaolin Wang
sprd_rtc_read_alarm(struct device * dev,struct rtc_wkalrm * alrm)383495bbde5SBaolin Wang static int sprd_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
384495bbde5SBaolin Wang {
385495bbde5SBaolin Wang struct sprd_rtc *rtc = dev_get_drvdata(dev);
386495bbde5SBaolin Wang time64_t secs;
387495bbde5SBaolin Wang int ret;
388495bbde5SBaolin Wang u32 val;
389495bbde5SBaolin Wang
390495bbde5SBaolin Wang /*
3917d9d4868SAlexandre Belloni * The RTC core checks to see if there is an alarm already set in RTC
3927d9d4868SAlexandre Belloni * hardware, and we always read the normal alarm at this time.
393495bbde5SBaolin Wang */
394495bbde5SBaolin Wang ret = sprd_rtc_get_secs(rtc, SPRD_RTC_ALARM, &secs);
395495bbde5SBaolin Wang if (ret)
396495bbde5SBaolin Wang return ret;
397495bbde5SBaolin Wang
398495bbde5SBaolin Wang rtc_time64_to_tm(secs, &alrm->time);
399495bbde5SBaolin Wang
400495bbde5SBaolin Wang ret = regmap_read(rtc->regmap, rtc->base + SPRD_RTC_INT_EN, &val);
401495bbde5SBaolin Wang if (ret)
402495bbde5SBaolin Wang return ret;
403495bbde5SBaolin Wang
404495bbde5SBaolin Wang alrm->enabled = !!(val & SPRD_RTC_ALARM_EN);
405495bbde5SBaolin Wang
406495bbde5SBaolin Wang ret = regmap_read(rtc->regmap, rtc->base + SPRD_RTC_INT_RAW_STS, &val);
407495bbde5SBaolin Wang if (ret)
408495bbde5SBaolin Wang return ret;
409495bbde5SBaolin Wang
410495bbde5SBaolin Wang alrm->pending = !!(val & SPRD_RTC_ALARM_EN);
411495bbde5SBaolin Wang return 0;
412495bbde5SBaolin Wang }
413495bbde5SBaolin Wang
sprd_rtc_set_alarm(struct device * dev,struct rtc_wkalrm * alrm)414495bbde5SBaolin Wang static int sprd_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
415495bbde5SBaolin Wang {
416495bbde5SBaolin Wang struct sprd_rtc *rtc = dev_get_drvdata(dev);
417495bbde5SBaolin Wang time64_t secs = rtc_tm_to_time64(&alrm->time);
418495bbde5SBaolin Wang struct rtc_time aie_time =
419495bbde5SBaolin Wang rtc_ktime_to_tm(rtc->rtc->aie_timer.node.expires);
420495bbde5SBaolin Wang int ret;
421495bbde5SBaolin Wang
422495bbde5SBaolin Wang /*
423495bbde5SBaolin Wang * We have 2 groups alarms: normal alarm and auxiliary alarm. Since
424495bbde5SBaolin Wang * both normal alarm event and auxiliary alarm event can wake up system
425495bbde5SBaolin Wang * from deep sleep, but only alarm event can power up system from power
426495bbde5SBaolin Wang * down status. Moreover we do not need to poll about 125ms when
427495bbde5SBaolin Wang * updating auxiliary alarm registers. Thus we usually set auxiliary
428495bbde5SBaolin Wang * alarm when wake up system from deep sleep, and for other scenarios,
429495bbde5SBaolin Wang * we should set normal alarm with polling status.
430495bbde5SBaolin Wang *
431495bbde5SBaolin Wang * So here we check if the alarm time is set by aie_timer, if yes, we
432495bbde5SBaolin Wang * should set normal alarm, if not, we should set auxiliary alarm which
433495bbde5SBaolin Wang * means it is just a wake event.
434495bbde5SBaolin Wang */
435495bbde5SBaolin Wang if (!rtc->rtc->aie_timer.enabled || rtc_tm_sub(&aie_time, &alrm->time))
436495bbde5SBaolin Wang return sprd_rtc_set_aux_alarm(dev, alrm);
437495bbde5SBaolin Wang
438495bbde5SBaolin Wang /* clear the alarm interrupt status firstly */
439495bbde5SBaolin Wang ret = regmap_write(rtc->regmap, rtc->base + SPRD_RTC_INT_CLR,
440495bbde5SBaolin Wang SPRD_RTC_ALARM_EN);
441495bbde5SBaolin Wang if (ret)
442495bbde5SBaolin Wang return ret;
443495bbde5SBaolin Wang
444495bbde5SBaolin Wang ret = sprd_rtc_set_secs(rtc, SPRD_RTC_ALARM, secs);
445495bbde5SBaolin Wang if (ret)
446495bbde5SBaolin Wang return ret;
447495bbde5SBaolin Wang
448495bbde5SBaolin Wang if (alrm->enabled) {
449495bbde5SBaolin Wang ret = regmap_update_bits(rtc->regmap,
450495bbde5SBaolin Wang rtc->base + SPRD_RTC_INT_EN,
451495bbde5SBaolin Wang SPRD_RTC_ALARM_EN,
452495bbde5SBaolin Wang SPRD_RTC_ALARM_EN);
453495bbde5SBaolin Wang if (ret)
454495bbde5SBaolin Wang return ret;
455495bbde5SBaolin Wang
456495bbde5SBaolin Wang /* unlock the alarm to enable the alarm function. */
457495bbde5SBaolin Wang ret = sprd_rtc_lock_alarm(rtc, false);
458495bbde5SBaolin Wang } else {
459495bbde5SBaolin Wang regmap_update_bits(rtc->regmap,
460495bbde5SBaolin Wang rtc->base + SPRD_RTC_INT_EN,
461495bbde5SBaolin Wang SPRD_RTC_ALARM_EN, 0);
462495bbde5SBaolin Wang
463495bbde5SBaolin Wang /*
464495bbde5SBaolin Wang * Lock the alarm function in case fake alarm event will power
465495bbde5SBaolin Wang * up systems.
466495bbde5SBaolin Wang */
467495bbde5SBaolin Wang ret = sprd_rtc_lock_alarm(rtc, true);
468495bbde5SBaolin Wang }
469495bbde5SBaolin Wang
470495bbde5SBaolin Wang return ret;
471495bbde5SBaolin Wang }
472495bbde5SBaolin Wang
sprd_rtc_alarm_irq_enable(struct device * dev,unsigned int enabled)473495bbde5SBaolin Wang static int sprd_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
474495bbde5SBaolin Wang {
475495bbde5SBaolin Wang struct sprd_rtc *rtc = dev_get_drvdata(dev);
476495bbde5SBaolin Wang int ret;
477495bbde5SBaolin Wang
478495bbde5SBaolin Wang if (enabled) {
479495bbde5SBaolin Wang ret = regmap_update_bits(rtc->regmap,
480495bbde5SBaolin Wang rtc->base + SPRD_RTC_INT_EN,
481495bbde5SBaolin Wang SPRD_RTC_ALARM_EN | SPRD_RTC_AUXALM_EN,
482495bbde5SBaolin Wang SPRD_RTC_ALARM_EN | SPRD_RTC_AUXALM_EN);
483495bbde5SBaolin Wang if (ret)
484495bbde5SBaolin Wang return ret;
485495bbde5SBaolin Wang
486495bbde5SBaolin Wang ret = sprd_rtc_lock_alarm(rtc, false);
487495bbde5SBaolin Wang } else {
488495bbde5SBaolin Wang regmap_update_bits(rtc->regmap, rtc->base + SPRD_RTC_INT_EN,
489495bbde5SBaolin Wang SPRD_RTC_ALARM_EN | SPRD_RTC_AUXALM_EN, 0);
490495bbde5SBaolin Wang
491495bbde5SBaolin Wang ret = sprd_rtc_lock_alarm(rtc, true);
492495bbde5SBaolin Wang }
493495bbde5SBaolin Wang
494495bbde5SBaolin Wang return ret;
495495bbde5SBaolin Wang }
496495bbde5SBaolin Wang
497495bbde5SBaolin Wang static const struct rtc_class_ops sprd_rtc_ops = {
498495bbde5SBaolin Wang .read_time = sprd_rtc_read_time,
499495bbde5SBaolin Wang .set_time = sprd_rtc_set_time,
500495bbde5SBaolin Wang .read_alarm = sprd_rtc_read_alarm,
501495bbde5SBaolin Wang .set_alarm = sprd_rtc_set_alarm,
502495bbde5SBaolin Wang .alarm_irq_enable = sprd_rtc_alarm_irq_enable,
503495bbde5SBaolin Wang };
504495bbde5SBaolin Wang
sprd_rtc_handler(int irq,void * dev_id)505495bbde5SBaolin Wang static irqreturn_t sprd_rtc_handler(int irq, void *dev_id)
506495bbde5SBaolin Wang {
507495bbde5SBaolin Wang struct sprd_rtc *rtc = dev_id;
508495bbde5SBaolin Wang int ret;
509495bbde5SBaolin Wang
510495bbde5SBaolin Wang ret = sprd_rtc_clear_alarm_ints(rtc);
511495bbde5SBaolin Wang if (ret)
512495bbde5SBaolin Wang return IRQ_RETVAL(ret);
513495bbde5SBaolin Wang
514495bbde5SBaolin Wang rtc_update_irq(rtc->rtc, 1, RTC_AF | RTC_IRQF);
515495bbde5SBaolin Wang return IRQ_HANDLED;
516495bbde5SBaolin Wang }
517495bbde5SBaolin Wang
sprd_rtc_check_power_down(struct sprd_rtc * rtc)518495bbde5SBaolin Wang static int sprd_rtc_check_power_down(struct sprd_rtc *rtc)
519495bbde5SBaolin Wang {
520495bbde5SBaolin Wang u32 val;
521495bbde5SBaolin Wang int ret;
522495bbde5SBaolin Wang
523a0defd7cSBaolin Wang ret = regmap_read(rtc->regmap, rtc->base + SPRD_RTC_PWR_STS, &val);
524495bbde5SBaolin Wang if (ret)
525495bbde5SBaolin Wang return ret;
526495bbde5SBaolin Wang
527495bbde5SBaolin Wang /*
528a0defd7cSBaolin Wang * If the RTC power status value is SPRD_RTC_POWER_RESET_VALUE, which
529a0defd7cSBaolin Wang * means the RTC has been powered down, so the RTC time values are
530a0defd7cSBaolin Wang * invalid.
531495bbde5SBaolin Wang */
532825156a5SKaixu Xia rtc->valid = val != SPRD_RTC_POWER_RESET_VALUE;
533495bbde5SBaolin Wang return 0;
534495bbde5SBaolin Wang }
535495bbde5SBaolin Wang
sprd_rtc_check_alarm_int(struct sprd_rtc * rtc)536bf2c532bSBaolin Wang static int sprd_rtc_check_alarm_int(struct sprd_rtc *rtc)
537bf2c532bSBaolin Wang {
538bf2c532bSBaolin Wang u32 val;
539bf2c532bSBaolin Wang int ret;
540bf2c532bSBaolin Wang
541bf2c532bSBaolin Wang ret = regmap_read(rtc->regmap, rtc->base + SPRD_RTC_SPG_VALUE, &val);
542bf2c532bSBaolin Wang if (ret)
543bf2c532bSBaolin Wang return ret;
544bf2c532bSBaolin Wang
545bf2c532bSBaolin Wang /*
546bf2c532bSBaolin Wang * The SPRD_RTC_INT_EN register is not put in always-power-on region
547bf2c532bSBaolin Wang * supplied by VDDRTC, so we should check if we need enable the alarm
548bf2c532bSBaolin Wang * interrupt when system booting.
549bf2c532bSBaolin Wang *
550bf2c532bSBaolin Wang * If we have set SPRD_RTC_POWEROFF_ALM_FLAG which is saved in
551bf2c532bSBaolin Wang * always-power-on region, that means we have set one alarm last time,
552bf2c532bSBaolin Wang * so we should enable the alarm interrupt to help RTC core to see if
553bf2c532bSBaolin Wang * there is an alarm already set in RTC hardware.
554bf2c532bSBaolin Wang */
555bf2c532bSBaolin Wang if (!(val & SPRD_RTC_POWEROFF_ALM_FLAG))
556bf2c532bSBaolin Wang return 0;
557bf2c532bSBaolin Wang
558bf2c532bSBaolin Wang return regmap_update_bits(rtc->regmap, rtc->base + SPRD_RTC_INT_EN,
559bf2c532bSBaolin Wang SPRD_RTC_ALARM_EN, SPRD_RTC_ALARM_EN);
560bf2c532bSBaolin Wang }
561bf2c532bSBaolin Wang
sprd_rtc_probe(struct platform_device * pdev)562495bbde5SBaolin Wang static int sprd_rtc_probe(struct platform_device *pdev)
563495bbde5SBaolin Wang {
564495bbde5SBaolin Wang struct device_node *node = pdev->dev.of_node;
565495bbde5SBaolin Wang struct sprd_rtc *rtc;
566495bbde5SBaolin Wang int ret;
567495bbde5SBaolin Wang
568495bbde5SBaolin Wang rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
569495bbde5SBaolin Wang if (!rtc)
570495bbde5SBaolin Wang return -ENOMEM;
571495bbde5SBaolin Wang
572495bbde5SBaolin Wang rtc->regmap = dev_get_regmap(pdev->dev.parent, NULL);
573495bbde5SBaolin Wang if (!rtc->regmap)
574495bbde5SBaolin Wang return -ENODEV;
575495bbde5SBaolin Wang
576495bbde5SBaolin Wang ret = of_property_read_u32(node, "reg", &rtc->base);
577495bbde5SBaolin Wang if (ret) {
578495bbde5SBaolin Wang dev_err(&pdev->dev, "failed to get RTC base address\n");
579495bbde5SBaolin Wang return ret;
580495bbde5SBaolin Wang }
581495bbde5SBaolin Wang
582495bbde5SBaolin Wang rtc->irq = platform_get_irq(pdev, 0);
583faac9102SStephen Boyd if (rtc->irq < 0)
584495bbde5SBaolin Wang return rtc->irq;
585495bbde5SBaolin Wang
586369a30a5SBaolin Wang rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
587369a30a5SBaolin Wang if (IS_ERR(rtc->rtc))
588369a30a5SBaolin Wang return PTR_ERR(rtc->rtc);
589369a30a5SBaolin Wang
590495bbde5SBaolin Wang rtc->dev = &pdev->dev;
591495bbde5SBaolin Wang platform_set_drvdata(pdev, rtc);
592495bbde5SBaolin Wang
593bf2c532bSBaolin Wang /* check if we need set the alarm interrupt */
594bf2c532bSBaolin Wang ret = sprd_rtc_check_alarm_int(rtc);
595bf2c532bSBaolin Wang if (ret) {
596bf2c532bSBaolin Wang dev_err(&pdev->dev, "failed to check RTC alarm interrupt\n");
597bf2c532bSBaolin Wang return ret;
598bf2c532bSBaolin Wang }
599bf2c532bSBaolin Wang
600495bbde5SBaolin Wang /* check if RTC time values are valid */
601495bbde5SBaolin Wang ret = sprd_rtc_check_power_down(rtc);
602495bbde5SBaolin Wang if (ret) {
603495bbde5SBaolin Wang dev_err(&pdev->dev, "failed to check RTC time values\n");
604495bbde5SBaolin Wang return ret;
605495bbde5SBaolin Wang }
606495bbde5SBaolin Wang
607495bbde5SBaolin Wang ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
608495bbde5SBaolin Wang sprd_rtc_handler,
609495bbde5SBaolin Wang IRQF_ONESHOT | IRQF_EARLY_RESUME,
610495bbde5SBaolin Wang pdev->name, rtc);
611495bbde5SBaolin Wang if (ret < 0) {
612495bbde5SBaolin Wang dev_err(&pdev->dev, "failed to request RTC irq\n");
613495bbde5SBaolin Wang return ret;
614495bbde5SBaolin Wang }
615495bbde5SBaolin Wang
616a86d6b23SBaolin Wang device_init_wakeup(&pdev->dev, 1);
617a86d6b23SBaolin Wang
618369a30a5SBaolin Wang rtc->rtc->ops = &sprd_rtc_ops;
619149aa91cSBaolin Wang rtc->rtc->range_min = 0;
620149aa91cSBaolin Wang rtc->rtc->range_max = 5662310399LL;
621fdcfd854SBartosz Golaszewski ret = devm_rtc_register_device(rtc->rtc);
622369a30a5SBaolin Wang if (ret) {
623a86d6b23SBaolin Wang device_init_wakeup(&pdev->dev, 0);
624369a30a5SBaolin Wang return ret;
625369a30a5SBaolin Wang }
626495bbde5SBaolin Wang
627495bbde5SBaolin Wang return 0;
628495bbde5SBaolin Wang }
629495bbde5SBaolin Wang
630495bbde5SBaolin Wang static const struct of_device_id sprd_rtc_of_match[] = {
631495bbde5SBaolin Wang { .compatible = "sprd,sc2731-rtc", },
632495bbde5SBaolin Wang { },
633495bbde5SBaolin Wang };
634495bbde5SBaolin Wang MODULE_DEVICE_TABLE(of, sprd_rtc_of_match);
635495bbde5SBaolin Wang
636495bbde5SBaolin Wang static struct platform_driver sprd_rtc_driver = {
637495bbde5SBaolin Wang .driver = {
638495bbde5SBaolin Wang .name = "sprd-rtc",
639495bbde5SBaolin Wang .of_match_table = sprd_rtc_of_match,
640495bbde5SBaolin Wang },
641495bbde5SBaolin Wang .probe = sprd_rtc_probe,
642495bbde5SBaolin Wang };
643495bbde5SBaolin Wang module_platform_driver(sprd_rtc_driver);
644495bbde5SBaolin Wang
645495bbde5SBaolin Wang MODULE_LICENSE("GPL v2");
646495bbde5SBaolin Wang MODULE_DESCRIPTION("Spreadtrum RTC Device Driver");
647495bbde5SBaolin Wang MODULE_AUTHOR("Baolin Wang <baolin.wang@spreadtrum.com>");
648