1 /*
2  * An RTC driver for Sunxi Platform of Allwinner SoC
3  *
4  * Copyright (c) 2013, Carlo Caione <carlo.caione@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  */
17 #include <hal_thread.h>
18 #include <hal_timer.h>
19 #include <stdlib.h>
20 #include <interrupt.h>
21 #include <rtc/rtc.h>
22 #include <sunxi_hal_rtc.h>
23 #include <hal_log.h>
24 #include <hal_interrupt.h>
25 
26 //for debug
27 #define CONFIG_DRIVERS_RTC_DEBUG
28 #ifdef CONFIG_DRIVERS_RTC_DEBUG
29 #define RTC_INFO(fmt, arg...) hal_log_info(fmt, ##arg)
30 #else
31 #define RTC_INFO(fmt, arg...) do {}while(0)
32 #endif
33 
34 #define RTC_ERR(fmt, arg...) hal_log_err(fmt, ##arg)
35 
36 static struct hal_rtc_dev sunxi_hal_rtc;
37 
38 static struct hal_rtc_data_year data_year_param =
39 {
40     .min        = 1970,
41     .max        = 2097,
42     .mask       = 0x7f,
43     .yshift     = 16,
44     .leap_shift = 23,
45 };
46 
hal_rtc_clk_init(struct hal_rtc_dev * rtc)47 static hal_rtc_status_t hal_rtc_clk_init(struct hal_rtc_dev *rtc)
48 {
49 #if defined(CONFIG_SOC_SUN20IW1)
50     hal_clk_type_t clk_r_type = HAL_SUNXI_R_CCU;
51     hal_clk_id_t rtc_clk_r_id = CLK_R_AHB_BUS_RTC;
52 
53     hal_clk_type_t clk_rtc1k_type = HAL_SUNXI_RTC_CCU;
54     hal_clk_id_t rtc_clk_rtc1k_id = CLK_RTC_1K;
55 
56     hal_clk_type_t clk_rtcspi_type = HAL_SUNXI_RTC_CCU;
57     hal_clk_id_t rtc_clk_rtcspi_id = CLK_RTC_SPI;
58 
59     hal_reset_type_t reset_type = HAL_SUNXI_RESET;
60     hal_reset_id_t rtc_reset_id = RST_R_AHB_BUS_RTC;
61 
62     rtc->bus_clk = hal_clock_get(clk_r_type, rtc_clk_r_id);
63     if(hal_clock_enable(rtc->bus_clk))
64     {
65     RTC_ERR("rtc bus clk enable failed!\n");
66     return RTC_ERROR;
67     }
68     rtc->rtc1k_clk = hal_clock_get(clk_rtc1k_type, rtc_clk_rtc1k_id);
69     if(hal_clock_enable(rtc->rtc1k_clk))
70     {
71     RTC_ERR("rtc 1k clk enable failed!\n");
72     return RTC_ERROR;
73     }
74     rtc->rtcspi_clk = hal_clock_get(clk_rtcspi_type, rtc_clk_rtcspi_id);
75     if(hal_clock_enable(rtc->rtcspi_clk))
76     {
77     RTC_ERR("rtc spi clk enable failed!\n");
78     return RTC_ERROR;
79     }
80 
81     rtc->reset = hal_reset_control_get(reset_type, rtc_reset_id);
82     if(hal_reset_control_deassert(rtc->reset))
83     {
84     RTC_ERR("rtc reset deassert failed!\n");
85     return RTC_ERROR;
86     }
87 #endif
88 
89     return RTC_OK;
90 }
91 
hal_rtc_write_data(int index,u32 val)92 void hal_rtc_write_data(int index, u32 val)
93 {
94     hal_writel(val, (unsigned long)SUNXI_RTC_DATA_BASE + index * 4);
95 }
96 
hal_rtc_read_data(int index)97 u32 hal_rtc_read_data(int index)
98 {
99     return hal_readl((unsigned long)SUNXI_RTC_DATA_BASE + index * 4);
100 }
101 
hal_rtc_set_fel_flag(void)102 void hal_rtc_set_fel_flag(void)
103 {
104     do
105     {
106         hal_rtc_write_data(RTC_FEL_INDEX, EFEX_FLAG);
107         isb();
108     } while (hal_rtc_read_data(RTC_FEL_INDEX) != EFEX_FLAG);
109 }
110 
hal_rtc_probe_fel_flag(void)111 u32 hal_rtc_probe_fel_flag(void)
112 {
113     return hal_rtc_read_data(RTC_FEL_INDEX) == EFEX_FLAG ? 1 : 0;
114 }
115 
hal_rtc_clear_fel_flag(void)116 void hal_rtc_clear_fel_flag(void)
117 {
118     do
119     {
120         hal_rtc_write_data(RTC_FEL_INDEX, 0);
121         isb();
122     } while (hal_rtc_read_data(RTC_FEL_INDEX) != 0);
123 }
124 
hal_rtc_set_bootmode_flag(u8 flag)125 int hal_rtc_set_bootmode_flag(u8 flag)
126 {
127     do
128     {
129         hal_rtc_write_data(RTC_BOOT_INDEX, flag);
130         isb();
131     } while (hal_rtc_read_data(RTC_BOOT_INDEX) != flag);
132 
133     return 0;
134 }
135 
hal_rtc_get_bootmode_flag(void)136 int hal_rtc_get_bootmode_flag(void)
137 {
138     int boot_flag;
139 
140     boot_flag = hal_rtc_read_data(RTC_BOOT_INDEX);
141 
142     return boot_flag;
143 }
144 
145 
hal_rtc_register_callback(rtc_callback_t user_callback)146 int hal_rtc_register_callback(rtc_callback_t user_callback)
147 {
148     struct hal_rtc_dev *rtc_dev = &sunxi_hal_rtc;
149 
150     if (user_callback == NULL)
151     {
152         return -1;
153     }
154 
155     rtc_dev->user_callback = user_callback;
156 
157     return 0;
158 }
159 
160 
hal_rtc_alarmirq(int irq,void * dev)161 static irqreturn_t hal_rtc_alarmirq(int irq, void *dev)
162 {
163     struct hal_rtc_dev *rtc_dev = (struct hal_rtc_dev *)dev;
164     u32 val;
165 
166     val = hal_readl(rtc_dev->base + SUNXI_ALRM_IRQ_STA);
167 
168     if (val & SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND)
169     {
170         val |= SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND;
171         hal_writel(val, rtc_dev->base + SUNXI_ALRM_IRQ_STA);
172 
173         if (rtc_dev->user_callback)
174         {
175             rtc_dev->user_callback();
176         }
177 
178         return 0;
179     }
180 
181     return -1;
182 }
183 
hal_rtc_setaie(int to,struct hal_rtc_dev * rtc_dev)184 static void hal_rtc_setaie(int to, struct hal_rtc_dev *rtc_dev)
185 {
186     u32 alrm_val = 0;
187     u32 alrm_irq_val = 0;
188 
189     if (to)
190     {
191         alrm_val = hal_readl(rtc_dev->base + SUNXI_ALRM_EN);
192         alrm_val |= SUNXI_ALRM_EN_CNT_EN;
193 
194         alrm_irq_val = hal_readl(rtc_dev->base + SUNXI_ALRM_IRQ_EN);
195         alrm_irq_val |= SUNXI_ALRM_IRQ_EN_CNT_IRQ_EN;
196     }
197     else
198     {
199         hal_writel(SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND,
200                rtc_dev->base + SUNXI_ALRM_IRQ_STA);
201     }
202 
203     hal_writel(alrm_val, rtc_dev->base + SUNXI_ALRM_EN);
204     hal_writel(alrm_irq_val, rtc_dev->base + SUNXI_ALRM_IRQ_EN);
205 }
206 
hal_rtc_wait(int offset,unsigned int mask,unsigned int ms_timeout)207 static int hal_rtc_wait(int offset, unsigned int mask, unsigned int ms_timeout)
208 {
209     struct hal_rtc_dev *rtc_dev = &sunxi_hal_rtc;
210     u32 reg;
211 
212     hal_msleep(ms_timeout);
213 
214     reg = hal_readl(rtc_dev->base + offset);
215     reg &= mask;
216 
217     if (reg != mask)
218     {
219         return 0;
220     }
221 
222     return -1;
223 }
224 
225 #ifdef SUNXI_SIMPLIFIED_TIMER
226 static short month_days[2][13] =
227 {
228     {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
229     {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
230 };
231 
hal_rtc_day_to_ymd(struct rtc_time * rtc_tm,u32 min_year,u32 udate)232 static int hal_rtc_day_to_ymd(struct rtc_time *rtc_tm, u32 min_year,
233                               u32 udate)
234 {
235     static u32 last_date;
236     static int last_year, last_mon, last_mday;
237     int year = 0, leap, i;
238     int date = (int)udate;
239 
240     if (date == last_date)
241     {
242         rtc_tm->tm_mday = last_mday;
243         rtc_tm->tm_mon = last_mon;
244         rtc_tm->tm_year = last_year;
245         return 0;
246     }
247 
248     year = min_year;
249     while (1)
250     {
251         if (is_leap_year(year))
252         {
253             if (date > 366)
254             {
255                 year++;
256                 date -= 366;
257             }
258             else
259             {
260                 break;
261             }
262         }
263         else
264         {
265             if (date > 365)
266             {
267                 year++;
268                 date -= 365;
269             }
270             else
271             {
272                 break;
273             }
274         }
275     }
276     rtc_tm->tm_year = year - 1900;
277     last_year = rtc_tm->tm_year;
278 
279     leap = is_leap_year(rtc_tm->tm_year);
280     for (i = 1; date > month_days[leap][i]; i++)
281     {
282         date -= month_days[leap][i];
283     }
284     rtc_tm->tm_mon = i;
285     last_mon = rtc_tm->tm_mon;
286     rtc_tm->tm_mday = date;
287     last_mday = rtc_tm->tm_mday;
288 
289     return 0;
290 }
291 #endif
292 
hal_rtc_gettime(struct rtc_time * rtc_tm)293 int hal_rtc_gettime(struct rtc_time *rtc_tm)
294 {
295     struct hal_rtc_dev *rtc_dev = &sunxi_hal_rtc;
296     u32 date, time;
297 
298     /*
299      * read again in case it changes
300      */
301     do
302     {
303         date = hal_readl(rtc_dev->base + SUNXI_RTC_YMD);
304         time = hal_readl(rtc_dev->base + SUNXI_RTC_HMS);
305     } while ((date != hal_readl(rtc_dev->base + SUNXI_RTC_YMD)) ||
306              (time != hal_readl(rtc_dev->base + SUNXI_RTC_HMS)));
307 
308     rtc_tm->tm_sec  = SUNXI_TIME_GET_SEC_VALUE(time);
309     rtc_tm->tm_min  = SUNXI_TIME_GET_MIN_VALUE(time);
310     rtc_tm->tm_hour = SUNXI_TIME_GET_HOUR_VALUE(time);
311 
312 #ifndef SUNXI_SIMPLIFIED_TIMER
313     rtc_tm->tm_mday = SUNXI_DATE_GET_DAY_VALUE(date);
314     rtc_tm->tm_mon  = SUNXI_DATE_GET_MON_VALUE(date);
315     rtc_tm->tm_year = SUNXI_DATE_GET_YEAR_VALUE(date, rtc_dev->data_year);
316 
317     /*
318      * switch from (data_year->min)-relative offset to
319      * a (1900)-relative one
320      */
321     rtc_tm->tm_year += SUNXI_YEAR_OFF(rtc_dev->data_year);
322 #else
323     hal_rtc_day_to_ymd(rtc_tm, rtc_dev->data_year->min, date);
324 #endif
325     rtc_tm->tm_mon  -= 1;
326 
327     RTC_INFO("Read hardware RTC time %04d-%02d-%02d %02d:%02d:%02d",
328              rtc_tm->tm_year + 1900, rtc_tm->tm_mon + 1, rtc_tm->tm_mday,
329              rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
330 
331     return 0;
332 }
333 
hal_rtc_settime(struct rtc_time * rtc_tm)334 int hal_rtc_settime(struct rtc_time *rtc_tm)
335 {
336     struct hal_rtc_dev *rtc_dev = &sunxi_hal_rtc;
337     u32 date = 0;
338     u32 time = 0;
339     int year;
340 #ifdef SUNXI_SIMPLIFIED_TIMER
341     int i, leap;
342 #endif
343     /*
344      * the input rtc_tm->tm_year is the offset relative to 1900. We use
345      * the SUNXI_YEAR_OFF macro to rebase it with respect to the min year
346      * allowed by the hardware
347      */
348 
349     year = rtc_tm->tm_year + 1900;
350     if (year < rtc_dev->data_year->min
351         || year > rtc_dev->data_year->max)
352     {
353         RTC_ERR("rtc only supports year in range %d - %d",
354                 rtc_dev->data_year->min, rtc_dev->data_year->max);
355         return -1;
356     }
357 
358 #ifndef SUNXI_SIMPLIFIED_TIMER
359     rtc_tm->tm_year -= SUNXI_YEAR_OFF(rtc_dev->data_year);
360     rtc_tm->tm_mon += 1;
361 
362     RTC_INFO("Will set hardware RTC time %04d-%02d-%02d %02d:%02d:%02d",
363              rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
364              rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
365 
366     date = SUNXI_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) |
367            SUNXI_DATE_SET_MON_VALUE(rtc_tm->tm_mon)  |
368            SUNXI_DATE_SET_YEAR_VALUE(rtc_tm->tm_year, rtc_dev->data_year);
369 
370     if (is_leap_year(year))
371     {
372         date |= SUNXI_LEAP_SET_VALUE(1, rtc_dev->data_year->leap_shift);
373     }
374 #else
375     date = rtc_tm->tm_mday;
376     rtc_tm->tm_mon += 1;
377     leap = is_leap_year(year);
378     for (i = 1; i < rtc_tm->tm_mon; i++)
379     {
380         date += month_days[leap][i];
381     }
382 
383     for (i = year - 1; i >= rtc_dev->data_year->min; i--)
384     {
385         if (is_leap_year(i))
386         {
387             date += 366;
388         }
389         else
390         {
391             date += 365;
392         }
393     }
394 #endif
395 
396     time = SUNXI_TIME_SET_SEC_VALUE(rtc_tm->tm_sec)  |
397            SUNXI_TIME_SET_MIN_VALUE(rtc_tm->tm_min)  |
398            SUNXI_TIME_SET_HOUR_VALUE(rtc_tm->tm_hour);
399 
400 
401     /*
402      * before we write the RTC HH-MM-SS register,we
403      * should check the SUNXI_LOSC_CTRL_RTC_HMS_ACC bit
404      */
405     if (hal_rtc_wait(SUNXI_LOSC_CTRL,
406                      SUNXI_LOSC_CTRL_RTC_HMS_ACC, 50))
407     {
408         RTC_ERR("Failed to set rtc time.");
409         return -1;
410     }
411 
412     hal_writel(0, rtc_dev->base + SUNXI_RTC_HMS);
413     /*
414      * After writing the RTC HH-MM-SS register, the
415      * SUNXI_LOSC_CTRL_RTC_HMS_ACC bit is set and it will not
416      * be cleared until the real writing operation is finished
417      */
418 
419     if (hal_rtc_wait(SUNXI_LOSC_CTRL, SUNXI_LOSC_CTRL_RTC_HMS_ACC, 50))
420     {
421         RTC_ERR("Failed to set rtc time.");
422         return -1;
423     }
424 
425     hal_writel(time, rtc_dev->base + SUNXI_RTC_HMS);
426 
427     /*
428      * After writing the RTC HH-MM-SS register, the
429      * SUNXI_LOSC_CTRL_RTC_HMS_ACC bit is set and it will not
430      * be cleared until the real writing operation is finished
431      */
432 
433     if (hal_rtc_wait(SUNXI_LOSC_CTRL, SUNXI_LOSC_CTRL_RTC_HMS_ACC, 50))
434     {
435         RTC_ERR("Failed to set rtc time.");
436         return -1;
437     }
438 
439     /*
440      * After writing the RTC YY-MM-DD register, the
441      * SUNXI_LOSC_CTRL_RTC_YMD_ACC bit is set and it will not
442      * be cleared until the real writing operation is finished
443      */
444 
445     if (hal_rtc_wait(SUNXI_LOSC_CTRL, SUNXI_LOSC_CTRL_RTC_YMD_ACC, 50))
446     {
447         RTC_ERR("Failed to set rtc time.");
448         return -1;
449     }
450     hal_msleep(2);
451 
452     hal_writel(date, rtc_dev->base + SUNXI_RTC_YMD);
453 
454     /*
455      * After writing the RTC YY-MM-DD register, the
456      * SUNXI_LOSC_CTRL_RTC_YMD_ACC bit is set and it will not
457      * be cleared until the real writing operation is finished
458      */
459 
460     if (hal_rtc_wait(SUNXI_LOSC_CTRL, SUNXI_LOSC_CTRL_RTC_YMD_ACC, 50))
461     {
462         RTC_ERR("Failed to set rtc time.");
463         return -1;
464     }
465     hal_msleep(2);
466 
467     return 0;
468 }
469 
hal_rtc_getalarm(struct rtc_wkalrm * wkalrm)470 int hal_rtc_getalarm(struct rtc_wkalrm *wkalrm)
471 {
472     struct hal_rtc_dev *rtc_dev = &sunxi_hal_rtc;
473     struct rtc_time *alrm_tm = &wkalrm->time;
474     u32 alrm_en;
475     unsigned int  alarm_cur = 0, alarm_cnt = 0;
476     unsigned long alarm_seconds = 0;
477     int ret;
478 
479 #ifdef SUNXI_ALARM1_USED
480     alrm = hal_readl(rtc_dev->base + SUNXI_ALRM_DHMS);
481     date = hal_readl(rtc_dev->base + SUNXI_RTC_YMD);
482 
483     alrm_tm->tm_sec = SUNXI_ALRM_GET_SEC_VALUE(alrm);
484     alrm_tm->tm_min = SUNXI_ALRM_GET_MIN_VALUE(alrm);
485     alrm_tm->tm_hour = SUNXI_ALRM_GET_HOUR_VALUE(alrm);
486 
487     alrm_tm->tm_mday = SUNXI_DATE_GET_DAY_VALUE(date);
488     alrm_tm->tm_mon = SUNXI_DATE_GET_MON_VALUE(date);
489     alrm_tm->tm_year = SUNXI_DATE_GET_YEAR_VALUE(date, rtc_dev->data_year);
490 
491     alrm_tm->tm_mon -= 1;
492 
493     /*
494      * switch from (data_year->min)-relative offset to
495      * a (1900)-relative one
496      */
497     alrm_tm->tm_year += SUNXI_YEAR_OFF(rtc_dev->data_year);
498 #else
499     alarm_cnt = hal_readl(rtc_dev->base + SUNXI_ALRM_COUNTER);
500     alarm_cur = hal_readl(rtc_dev->base + SUNXI_ALRM_CURRENT);
501 
502     RTC_INFO("alarm_cnt: %d, alarm_cur: %d", alarm_cnt, alarm_cur);
503     if (alarm_cur > alarm_cnt)
504     {
505         /* alarm is disabled. */
506         wkalrm->enabled = 0;
507         alrm_tm->tm_mon = -1;
508         alrm_tm->tm_mday = -1;
509         alrm_tm->tm_year = -1;
510         alrm_tm->tm_hour = -1;
511         alrm_tm->tm_min = -1;
512         alrm_tm->tm_sec = -1;
513         return 0;
514     }
515 
516     ret = hal_rtc_gettime(alrm_tm);
517     if (ret)
518     {
519         return -1;
520     }
521 
522     rtc_tm_to_time(alrm_tm, &alarm_seconds);
523     alarm_cnt = (alarm_cnt - alarm_cur);
524     alarm_cur = 0;
525     alarm_seconds += alarm_cnt;
526 
527     rtc_time_to_tm(alarm_seconds, alrm_tm);
528     RTC_INFO("alarm_seconds: %ld", alarm_seconds);
529 
530 #endif
531 
532     alrm_en = hal_readl(rtc_dev->base + SUNXI_ALRM_IRQ_EN);
533     if (alrm_en & SUNXI_ALRM_EN_CNT_EN)
534     {
535         wkalrm->enabled = 1;
536     }
537 
538     return 0;
539 }
540 
541 
hal_rtc_setalarm(struct rtc_wkalrm * wkalrm)542 int hal_rtc_setalarm(struct rtc_wkalrm *wkalrm)
543 {
544 
545     struct hal_rtc_dev *rtc_dev = &sunxi_hal_rtc;
546     struct rtc_time *alrm_tm = &wkalrm->time;
547     struct rtc_time tm_now;
548     u32 alrm;
549     time64_t diff;
550     unsigned long time_gap;
551     unsigned long time_gap_day;
552 #if defined(SUNXI_ALARM1_USED)
553     unsigned long time_gap_hour = 0;
554     unsigned long time_gap_min = 0;
555 #endif
556     int ret;
557     ret = hal_rtc_gettime(&tm_now);
558     if (ret < 0)
559     {
560         RTC_ERR("Error in getting time");
561         return -1;
562     }
563 
564     diff = rtc_tm_sub(alrm_tm, &tm_now);
565     if (diff <= 0)
566     {
567         RTC_ERR("Date to set in the past");
568         return -1;
569     }
570 
571     if (diff > 255 * SEC_IN_DAY)
572     {
573         RTC_ERR("Day must be in the range 0 - 255");
574         return -1;
575     }
576 
577     time_gap = diff;
578     time_gap_day = alrm_tm->tm_mday - tm_now.tm_mday;
579 #ifdef SUNXI_SIMPLIFIED_TIMER
580     hal_rtc_setaie(0, rtc_dev);
581 
582     hal_writel(0, rtc_dev->base + SUNXI_ALRM_DAY);
583 
584     hal_writel(0, rtc_dev->base + SUNXI_ALRM_HMS);
585 
586     hal_writel(time_gap_day + hal_readl(rtc_dev->base + SUNXI_RTC_YMD),
587            rtc_dev->base + SUNXI_ALRM_DAY);
588 
589     alrm = SUNXI_ALRM_SET_SEC_VALUE(alrm_tm->tm_sec) |
590            SUNXI_ALRM_SET_MIN_VALUE(alrm_tm->tm_min) |
591            SUNXI_ALRM_SET_HOUR_VALUE(alrm_tm->tm_hour);
592 
593     hal_writel(alrm, rtc_dev->base + SUNXI_ALRM_HMS);
594 
595 #else
596 #ifdef SUNXI_ALARM1_USED
597     time_gap -= time_gap_day * SEC_IN_DAY;
598     time_gap_hour = time_gap / SEC_IN_HOUR;
599     time_gap -= time_gap_hour * SEC_IN_HOUR;
600     time_gap_min = time_gap / SEC_IN_MIN;
601     time_gap -= time_gap_min * SEC_IN_MIN;
602 #endif
603 
604     hal_rtc_setaie(0, rtc_dev);
605 #ifdef SUNXI_ALARM1_USED
606     if (hal_rtc_wait(SUNXI_LOSC_CTRL,
607                      SUNXI_LOSC_CTRL_RTC_ALARM_ACC, 50))
608     {
609         RTC_ERR("Failed to set rtc alarm1.");
610         return -1;
611     }
612     hal_msleep(2);
613 
614     hal_writel(0, rtc_dev->base + SUNXI_ALRM_DHMS);
615     if (hal_rtc_wait(SUNXI_LOSC_CTRL,
616                      SUNXI_LOSC_CTRL_RTC_ALARM_ACC, 50))
617     {
618         RTC_ERR("Failed to set rtc alarm1.");
619         return -1;
620     }
621     hal_msleep(2);
622 
623     alrm = SUNXI_ALRM_SET_SEC_VALUE(time_gap) |
624            SUNXI_ALRM_SET_MIN_VALUE(time_gap_min) |
625            SUNXI_ALRM_SET_HOUR_VALUE(time_gap_hour) |
626            SUNXI_ALRM_SET_DAY_VALUE(time_gap_day);
627     hal_writel(alrm, rtc_dev->base + SUNXI_ALRM_DHMS);
628     if (hal_rtc_wait(SUNXI_LOSC_CTRL,
629                      SUNXI_LOSC_CTRL_RTC_ALARM_ACC, 50))
630     {
631         RTC_ERR("Failed to set rtc alarm1.");
632         return -1;
633     }
634     hal_msleep(2);
635 #else
636     hal_writel(0, rtc_dev->base + SUNXI_ALRM_COUNTER);
637     alrm = time_gap;
638 
639     RTC_INFO("set alarm seconds:%d enable:%d", alrm, wkalrm->enabled);
640     hal_writel(alrm, rtc_dev->base + SUNXI_ALRM_COUNTER);
641 #endif
642 
643 #endif
644 
645     hal_writel(0, rtc_dev->base + SUNXI_ALRM_IRQ_EN);
646     hal_writel(SUNXI_ALRM_IRQ_EN_CNT_IRQ_EN, rtc_dev->base + SUNXI_ALRM_IRQ_EN);
647 
648     hal_rtc_setaie(wkalrm->enabled, rtc_dev);
649 
650     return 0;
651 }
652 
hal_rtc_alarm_irq_enable(unsigned int enabled)653 int hal_rtc_alarm_irq_enable(unsigned int enabled)
654 {
655     struct hal_rtc_dev *rtc_dev = &sunxi_hal_rtc;
656 
657     hal_rtc_setaie(enabled, rtc_dev);
658 
659     return 0;
660 }
661 
hal_rtc_min_year_show(unsigned int * min)662 void hal_rtc_min_year_show(unsigned int *min)
663 {
664     struct hal_rtc_dev *rtc_dev = &sunxi_hal_rtc;
665 
666     *min = rtc_dev->data_year->min;
667 
668     RTC_INFO("sunxi rtc max year:%d", *min);
669 }
670 
hal_rtc_max_year_show(unsigned int * max)671 void hal_rtc_max_year_show(unsigned int *max)
672 {
673     struct hal_rtc_dev *rtc_dev = &sunxi_hal_rtc;
674 
675     *max = rtc_dev->data_year->max;
676 
677     RTC_INFO("sunxi rtc max year:%d", *max);
678 }
679 
hal_rtc_init(void)680 int hal_rtc_init(void)
681 {
682     struct hal_rtc_dev *rtc_dev = &sunxi_hal_rtc;
683     int ret;
684     unsigned int tmp_data;
685 
686     rtc_dev->base = SUNXI_RTC_BASE;
687     rtc_dev->data_year = (struct hal_rtc_data_year *) &data_year_param;
688 
689     hal_writel(0, rtc_dev->base + SUNXI_ALRM_COUNTER);
690 
691     /* disable alarm, not generate irq pending */
692     hal_writel(0, rtc_dev->base + SUNXI_ALRM_EN);
693 
694     /* disable alarm week/cnt irq, unset to cpu */
695     hal_writel(0, rtc_dev->base + SUNXI_ALRM_IRQ_EN);
696 
697     /* clear alarm week/cnt irq pending */
698     hal_writel(SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND, rtc_dev->base +
699            SUNXI_ALRM_IRQ_STA);
700 
701     /* clear alarm wakeup output */
702     hal_writel(SUNXI_ALRM_WAKEUP_OUTPUT_EN, rtc_dev->base +
703            SUNXI_ALARM_CONFIG);
704 
705     if(hal_rtc_clk_init(rtc_dev))
706     {
707     RTC_ERR("rtc init clk error!\n");
708     return RTC_CLK_ERROR;
709     }
710 
711     /*
712     * Step1: select RTC clock source
713     */
714     tmp_data = hal_readl(rtc_dev->base + SUNXI_LOSC_CTRL);
715     tmp_data |= (REG_CLK32K_AUTO_SWT_EN);
716 
717     /* Enable auto switch function */
718     tmp_data &= (~REG_CLK32K_AUTO_SWT_BYPASS);
719     hal_writel(tmp_data, rtc_dev->base + SUNXI_LOSC_CTRL);
720 
721     tmp_data = hal_readl(rtc_dev->base + SUNXI_LOSC_CTRL);
722     tmp_data |= (RTC_SOURCE_EXTERNAL | REG_LOSCCTRL_MAGIC);
723     hal_writel(tmp_data, rtc_dev->base + SUNXI_LOSC_CTRL);
724 
725     /* We need to set GSM after change clock source */
726     tmp_data = hal_readl(rtc_dev->base + SUNXI_LOSC_CTRL);
727     tmp_data |= (EXT_LOSC_GSM | REG_LOSCCTRL_MAGIC);
728     hal_writel(tmp_data, rtc_dev->base + SUNXI_LOSC_CTRL);
729     rtc_dev->irq = SUXNI_IRQ_RTC;
730 
731     ret = request_irq(rtc_dev->irq, hal_rtc_alarmirq, 0, "rtc-ctrl", rtc_dev);
732     if (ret)
733     {
734         RTC_ERR("Could not request IRQ");
735         return -1;
736     }
737     enable_irq(rtc_dev->irq);
738     RTC_INFO("RTC enabled");
739 
740     return 0;
741 }
742 
hal_rtc_deinit(void)743 int hal_rtc_deinit(void)
744 {
745     struct hal_rtc_dev *rtc_dev = &sunxi_hal_rtc;
746 #if defined(CONFIG_SOC_SUN20IW1)
747     hal_clock_disable(rtc_dev->bus_clk);
748     hal_clock_put(rtc_dev->bus_clk);
749     hal_clock_disable(rtc_dev->rtc1k_clk);
750     hal_clock_put(rtc_dev->rtc1k_clk);
751     hal_clock_disable(rtc_dev->rtcspi_clk);
752     hal_clock_put(rtc_dev->rtcspi_clk);
753     hal_reset_control_assert(rtc_dev->reset);
754     hal_reset_control_put(rtc_dev->reset);
755 #endif
756     free_irq(rtc_dev->irq, rtc_dev);
757     return 0;
758 }
759 
760