Improve the process for GNU tools
[minix3.git] / minix / drivers / power / tps65950 / rtc.c
blob9a683556a9f82143d8548c747de01ce136a7a8f4
1 #include <minix/ds.h>
2 #include <minix/drivers.h>
3 #include <minix/i2c.h>
4 #include <minix/i2cdriver.h>
5 #include <minix/log.h>
7 #include <time.h>
9 #include "tps65950.h"
10 #include "rtc.h"
12 /* logging - use with log_warn(), log_info(), log_debug(), log_trace(), etc */
13 static struct log log = {
14 .name = "tps65950.rtc",
15 .log_level = LEVEL_INFO,
16 .log_func = default_log
19 static int bcd_to_dec(int n);
20 static int dec_to_bcd(int n);
22 int
23 rtc_init(void)
25 int r;
26 uint8_t val;
27 struct tm t;
29 r = i2creg_set_bits8(bus_endpoint, addresses[ID4], RTC_CTRL_REG,
30 (1 << STOP_RTC_BIT));
31 if (r != OK) {
32 log_warn(&log, "Failed to start RTC\n");
33 return -1;
36 r = i2creg_read8(bus_endpoint, addresses[ID4], RTC_STATUS_REG, &val);
37 if (r != OK) {
38 log_warn(&log, "Failed to read RTC_STATUS_REG\n");
39 return -1;
42 if ((val & (1 << RUN_BIT)) != (1 << RUN_BIT)) {
43 log_warn(&log, "RTC did not start. Bad MSECURE?\n");
44 return -1;
47 log_debug(&log, "RTC Started\n");
49 return OK;
52 int
53 rtc_get_time(struct tm *t, int flags)
55 int r;
56 uint8_t val;
58 memset(t, '\0', sizeof(struct tm));
60 /* Write GET_TIME_BIT to RTC_CTRL_REG to latch the RTC values into
61 * the RTC registers. This is required before each read.
63 r = i2creg_set_bits8(bus_endpoint, addresses[ID4], RTC_CTRL_REG,
64 (1 << GET_TIME_BIT));
65 if (r != OK) {
66 return -1;
69 /* Read and Convert BCD to binary (default RTC mode). */
71 /* Seconds - 0 to 59 */
72 r = i2creg_read8(bus_endpoint, addresses[ID4], SECONDS_REG, &val);
73 if (r != OK) {
74 return -1;
76 t->tm_sec = bcd_to_dec(val & 0x7f);
78 /* Minutes - 0 to 59 */
79 r = i2creg_read8(bus_endpoint, addresses[ID4], MINUTES_REG, &val);
80 if (r != OK) {
81 return -1;
83 t->tm_min = bcd_to_dec(val & 0x7f);
85 /* Hours - 0 to 23 */
86 r = i2creg_read8(bus_endpoint, addresses[ID4], HOURS_REG, &val);
87 if (r != OK) {
88 return -1;
90 t->tm_hour = bcd_to_dec(val & 0x3f);
92 /* Days - 1 to 31 */
93 r = i2creg_read8(bus_endpoint, addresses[ID4], DAYS_REG, &val);
94 if (r != OK) {
95 return -1;
97 t->tm_mday = bcd_to_dec(val & 0x3f);
99 /* Months - Jan=1 to Dec=12 */
100 r = i2creg_read8(bus_endpoint, addresses[ID4], MONTHS_REG, &val);
101 if (r != OK) {
102 return -1;
104 t->tm_mon = bcd_to_dec(val & 0x1f) - 1;
106 /* Years - last 2 digits of year */
107 r = i2creg_read8(bus_endpoint, addresses[ID4], YEARS_REG, &val);
108 if (r != OK) {
109 return -1;
111 t->tm_year = bcd_to_dec(val & 0x1f) + 100;
113 if (t->tm_year == 100) {
114 /* Cold start - no date/time set - default to 2013-01-01 */
115 t->tm_sec = 0;
116 t->tm_min = 0;
117 t->tm_hour = 0;
118 t->tm_mday = 1;
119 t->tm_mon = 0;
120 t->tm_year = 113;
122 rtc_set_time(t, RTCDEV_NOFLAGS);
125 return OK;
129 rtc_set_time(struct tm *t, int flags)
131 int r;
133 /* Write the date/time to the RTC registers. */
134 r = i2creg_write8(bus_endpoint, addresses[ID4], SECONDS_REG,
135 (dec_to_bcd(t->tm_sec) & 0x7f));
136 if (r != OK) {
137 return -1;
140 r = i2creg_write8(bus_endpoint, addresses[ID4], MINUTES_REG,
141 (dec_to_bcd(t->tm_min) & 0x7f));
142 if (r != OK) {
143 return -1;
146 r = i2creg_write8(bus_endpoint, addresses[ID4], HOURS_REG,
147 (dec_to_bcd(t->tm_hour) & 0x3f));
148 if (r != OK) {
149 return -1;
152 r = i2creg_write8(bus_endpoint, addresses[ID4], DAYS_REG,
153 (dec_to_bcd(t->tm_mday) & 0x3f));
154 if (r != OK) {
155 return -1;
158 r = i2creg_write8(bus_endpoint, addresses[ID4], MONTHS_REG,
159 (dec_to_bcd(t->tm_mon + 1) & 0x1f));
160 if (r != OK) {
161 return -1;
164 r = i2creg_write8(bus_endpoint, addresses[ID4], YEARS_REG,
165 (dec_to_bcd(t->tm_year % 100) & 0xff));
166 if (r != OK) {
167 return -1;
170 return OK;
174 rtc_exit(void)
176 return OK;
179 static int
180 bcd_to_dec(int n)
182 return ((n >> 4) & 0x0F) * 10 + (n & 0x0F);
185 static int
186 dec_to_bcd(int n)
188 return ((n / 10) << 4) | (n % 10);