hal_rtc.c 19 KB

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