coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
rtc.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <soc/rtc_common.h>
4 #include <soc/rtc.h>
5 #include <timer.h>
6 
7 /* ensure rtc write success */
8 static bool rtc_busy_wait(void)
9 {
10  struct stopwatch sw;
11  u16 bbpu;
12 
14 
15  do {
16  rtc_read(RTC_BBPU, &bbpu);
17  /* Time > 1sec, time out and set recovery mode enable.*/
18  if (stopwatch_expired(&sw)) {
19  rtc_info("BBPU CBUSY time out !!\n");
20  return false;
21  }
22  } while (bbpu & RTC_BBPU_CBUSY);
23 
24  return true;
25 }
26 
28 {
29  rtc_write(RTC_WRTGR, 1);
30  return rtc_busy_wait();
31 }
32 
33 /* unlock rtc write interface */
35 {
37  if (!rtc_write_trigger())
38  return false;
40  if (!rtc_write_trigger())
41  return false;
42 
43  return true;
44 }
45 
46 /* set rtc time */
47 int rtc_set(const struct rtc_time *time)
48 {
49  return -1;
50 }
51 
52 /* get rtc time */
53 int rtc_get(struct rtc_time *time)
54 {
55  u16 value;
56 
58  time->sec = value;
60  time->min = value;
62  time->hour = value;
64  time->mday = value;
66  time->mon = value;
68  time->year = (value + RTC_MIN_YEAR_OFFSET) % 100;
69 
70  return 0;
71 }
72 
73 /* set rtc xosc setting */
75 {
76  u16 bbpu;
77 
79  if (!rtc_busy_wait())
80  return false;
82  if (!rtc_busy_wait())
83  return false;
84 
86  if (!rtc_busy_wait())
87  return false;
88 
89  rtc_read(RTC_BBPU, &bbpu);
90  bbpu |= RTC_BBPU_KEY | RTC_BBPU_RELOAD;
91  rtc_write(RTC_BBPU, bbpu);
92 
93  return rtc_write_trigger();
94 }
95 
96 /* enable lpd subroutine */
97 bool rtc_lpen(u16 con)
98 {
99  con &= ~RTC_CON_LPRST;
100  rtc_write(RTC_CON, con);
101 
102  if (!rtc_write_trigger())
103  return false;
104 
105  con |= RTC_CON_LPRST;
106  rtc_write(RTC_CON, con);
107 
108  if (!rtc_write_trigger())
109  return false;
110 
111  con &= ~RTC_CON_LPRST;
112  rtc_write(RTC_CON, con);
113 
114  if (!rtc_write_trigger())
115  return false;
116 
117  return true;
118 }
119 
120 /* initialize rtc related registers */
121 bool rtc_reg_init(void)
122 {
123  u16 irqsta;
124 
125  rtc_write(RTC_IRQ_EN, 0);
126  rtc_write(RTC_CII_EN, 0);
129  rtc_write(RTC_AL_MTH, 1);
130  rtc_write(RTC_AL_DOM, 1);
131  rtc_write(RTC_AL_DOW, 4);
132  rtc_write(RTC_AL_HOU, 0);
133  rtc_write(RTC_AL_MIN, 0);
134  rtc_write(RTC_AL_SEC, 0);
135 
136  rtc_write(RTC_DIFF, 0);
137  rtc_write(RTC_CALI, 0);
138  if (!rtc_write_trigger())
139  return false;
140 
141  rtc_read(RTC_IRQ_STA, &irqsta); /* read clear */
142 
143  /* init time counters after resetting RTC_DIFF and RTC_CALI */
148  rtc_write(RTC_TC_HOU, 0);
149  rtc_write(RTC_TC_MIN, 0);
150  rtc_write(RTC_TC_SEC, 0);
151 
152  return rtc_write_trigger();
153 }
154 
155 /* write powerkeys to enable rtc functions */
157 {
160  return rtc_write_trigger();
161 }
162 
163 static u8 rtc_check_state(void)
164 {
165  u16 con;
166  u16 pwrky1;
167  u16 pwrky2;
168 
169  rtc_read(RTC_CON, &con);
170  rtc_read(RTC_POWERKEY1, &pwrky1);
171  rtc_read(RTC_POWERKEY2, &pwrky2);
172 
173  rtc_info("con=%x, pwrkey1=%x, pwrkey2=%x\n", con, pwrky1, pwrky2);
174 
175  if (con & RTC_CON_LPSTA_RAW)
176  return RTC_STATE_INIT;
177 
178  if (!rtc_busy_wait())
179  return RTC_STATE_RECOVER;
180 
181  if (!rtc_writeif_unlock())
182  return RTC_STATE_RECOVER;
183 
184  if (pwrky1 != RTC_POWERKEY1_KEY || pwrky2 != RTC_POWERKEY2_KEY)
185  return RTC_STATE_INIT;
186  else
187  return RTC_STATE_REBOOT;
188 }
189 
190 void rtc_boot_common(void)
191 {
192  u16 bbpu;
193  u16 con;
194  u16 irqsta;
195 
196  switch (rtc_check_state()) {
197  case RTC_STATE_REBOOT:
198  rtc_read(RTC_BBPU, &bbpu);
201  rtc_osc_init();
202  rtc_info("RTC_STATE_REBOOT\n");
203  break;
204  case RTC_STATE_RECOVER:
205  rtc_init(1);
206  rtc_info("RTC_STATE_RECOVER\n");
207  break;
208  case RTC_STATE_INIT:
209  default:
210  if (rtc_init(0))
211  rtc_init(1);
212  rtc_info("RTC_STATE_INIT\n");
213  break;
214  }
215 
216  rtc_read(RTC_IRQ_STA, &irqsta); /* Read clear */
217  rtc_read(RTC_BBPU, &bbpu);
218  rtc_read(RTC_CON, &con);
219 
220  rtc_info("irqsta=%x, bbpu=%x, con=%x\n", irqsta, bbpu, con);
221 }
pte_t value
Definition: mmu.c:91
static int stopwatch_expired(struct stopwatch *sw)
Definition: timer.h:152
static void stopwatch_init_usecs_expire(struct stopwatch *sw, long us)
Definition: timer.h:127
#define rtc_info(fmt, arg ...)
Definition: rtc_common.h:12
@ RTC_STATE_INIT
Definition: rtc_common.h:82
@ RTC_STATE_REBOOT
Definition: rtc_common.h:80
@ RTC_STATE_RECOVER
Definition: rtc_common.h:81
@ RTC_BBPU_KEY
Definition: rtc_common.h:45
@ RTC_OSC32CON_UNLOCK2
Definition: rtc_common.h:36
@ RTC_OSC32CON_UNLOCK1
Definition: rtc_common.h:35
@ RTC_MIN_YEAR_OFFSET
Definition: rtc_common.h:74
@ RTC_MIN_YEAR
Definition: rtc_common.h:72
@ RTC_DEFAULT_DOM
Definition: rtc_common.h:25
@ RTC_DEFAULT_MTH
Definition: rtc_common.h:24
@ RTC_DEFAULT_YEA
Definition: rtc_common.h:23
@ RTC_DEFAULT_DOW
Definition: rtc_common.h:26
@ RTC_POWERKEY1_KEY
Definition: rtc_common.h:63
@ RTC_POWERKEY2_KEY
Definition: rtc_common.h:64
@ RTC_PROT_UNLOCK2
Definition: rtc_common.h:41
@ RTC_PROT_UNLOCK1
Definition: rtc_common.h:40
void rtc_read(u16 addr, u16 *rdata)
Definition: rtc_mt6359p.c:14
void rtc_write(u16 addr, u16 wdata)
Definition: rtc_mt6359p.c:25
void rtc_init(void)
Definition: rtc.c:29
static u8 rtc_check_state(void)
Definition: rtc.c:163
bool rtc_write_trigger(void)
Definition: rtc.c:27
static bool rtc_busy_wait(void)
Definition: rtc.c:8
bool rtc_lpen(u16 con)
Definition: rtc.c:97
int rtc_set(const struct rtc_time *time)
Definition: rtc.c:47
bool rtc_writeif_unlock(void)
Definition: rtc.c:34
int rtc_get(struct rtc_time *time)
Definition: rtc.c:53
bool rtc_reg_init(void)
Definition: rtc.c:121
void rtc_boot_common(void)
Definition: rtc.c:190
bool rtc_xosc_write(u16 val)
Definition: rtc.c:74
bool rtc_powerkey_init(void)
Definition: rtc.c:156
@ RTC_WRTGR
Definition: rtc.h:44
@ RTC_CON
Definition: rtc.h:43
@ RTC_OSC32CON
Definition: rtc.h:42
@ RTC_IRQ_EN
Definition: rtc.h:16
@ RTC_IRQ_STA
Definition: rtc.h:15
@ RTC_BBPU
Definition: rtc.h:14
@ RTC_CII_EN
Definition: rtc.h:17
@ RTC_CBUSY_TIMEOUT_US
Definition: rtc.h:70
@ RTC_BBPU_RELOAD
Definition: rtc.h:67
@ RTC_BBPU_CBUSY
Definition: rtc.h:68
@ RTC_CON_LPSTA_RAW
Definition: rtc.h:92
@ RTC_CON_LPRST
Definition: rtc.h:80
@ RTC_DIFF
Definition: rtc.h:58
@ RTC_CALI
Definition: rtc.h:59
@ RTC_PROT
Definition: rtc.h:57
@ RTC_AL_MTH
Definition: rtc.h:36
@ RTC_AL_DOM
Definition: rtc.h:34
@ RTC_AL_DOW
Definition: rtc.h:35
@ RTC_AL_MIN
Definition: rtc.h:32
@ RTC_AL_HOU
Definition: rtc.h:33
@ RTC_AL_MASK
Definition: rtc.h:38
@ RTC_AL_YEA
Definition: rtc.h:37
@ RTC_AL_SEC
Definition: rtc.h:31
@ RTC_TC_MTH
Definition: rtc.h:26
@ RTC_TC_SEC
Definition: rtc.h:21
@ RTC_TC_MIN
Definition: rtc.h:22
@ RTC_TC_DOW
Definition: rtc.h:25
@ RTC_TC_DOM
Definition: rtc.h:24
@ RTC_TC_YEA
Definition: rtc.h:27
@ RTC_TC_HOU
Definition: rtc.h:23
@ RTC_POWERKEY1
Definition: rtc.h:48
@ RTC_POWERKEY2
Definition: rtc.h:49
void rtc_osc_init(void)
Definition: rtc.c:28
uint16_t u16
Definition: stdint.h:48
uint8_t u8
Definition: stdint.h:45
Definition: rtc.h:6
int year
Definition: rtc.h:12
int hour
Definition: rtc.h:9
int mon
Definition: rtc.h:11
int min
Definition: rtc.h:8
int sec
Definition: rtc.h:7
int mday
Definition: rtc.h:10
u8 val
Definition: sys.c:300