xref: /minix3/minix/drivers/power/tps65950/rtc.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
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>
6 
7 #include <time.h>
8 
9 #include "tps65950.h"
10 #include "rtc.h"
11 
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
17 };
18 
19 static int bcd_to_dec(int n);
20 static int dec_to_bcd(int n);
21 
22 int
rtc_init(void)23 rtc_init(void)
24 {
25 	int r;
26 	uint8_t val;
27 	struct tm t;
28 
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;
34 	}
35 
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;
40 	}
41 
42 	if ((val & (1 << RUN_BIT)) != (1 << RUN_BIT)) {
43 		log_warn(&log, "RTC did not start. Bad MSECURE?\n");
44 		return -1;
45 	}
46 
47 	log_debug(&log, "RTC Started\n");
48 
49 	return OK;
50 }
51 
52 int
rtc_get_time(struct tm * t,int flags)53 rtc_get_time(struct tm *t, int flags)
54 {
55 	int r;
56 	uint8_t val;
57 
58 	memset(t, '\0', sizeof(struct tm));
59 
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.
62 	 */
63 	r = i2creg_set_bits8(bus_endpoint, addresses[ID4], RTC_CTRL_REG,
64 	    (1 << GET_TIME_BIT));
65 	if (r != OK) {
66 		return -1;
67 	}
68 
69 	/* Read and Convert BCD to binary (default RTC mode). */
70 
71 	/* Seconds - 0 to 59 */
72 	r = i2creg_read8(bus_endpoint, addresses[ID4], SECONDS_REG, &val);
73 	if (r != OK) {
74 		return -1;
75 	}
76 	t->tm_sec = bcd_to_dec(val & 0x7f);
77 
78 	/* Minutes - 0 to 59 */
79 	r = i2creg_read8(bus_endpoint, addresses[ID4], MINUTES_REG, &val);
80 	if (r != OK) {
81 		return -1;
82 	}
83 	t->tm_min = bcd_to_dec(val & 0x7f);
84 
85 	/* Hours - 0 to 23 */
86 	r = i2creg_read8(bus_endpoint, addresses[ID4], HOURS_REG, &val);
87 	if (r != OK) {
88 		return -1;
89 	}
90 	t->tm_hour = bcd_to_dec(val & 0x3f);
91 
92 	/* Days - 1 to 31 */
93 	r = i2creg_read8(bus_endpoint, addresses[ID4], DAYS_REG, &val);
94 	if (r != OK) {
95 		return -1;
96 	}
97 	t->tm_mday = bcd_to_dec(val & 0x3f);
98 
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;
103 	}
104 	t->tm_mon = bcd_to_dec(val & 0x1f) - 1;
105 
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;
110 	}
111 	t->tm_year = bcd_to_dec(val & 0x1f) + 100;
112 
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;
121 
122 		rtc_set_time(t, RTCDEV_NOFLAGS);
123 	}
124 
125 	return OK;
126 }
127 
128 int
rtc_set_time(struct tm * t,int flags)129 rtc_set_time(struct tm *t, int flags)
130 {
131 	int r;
132 
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;
138 	}
139 
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;
144 	}
145 
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;
150 	}
151 
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;
156 	}
157 
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;
162 	}
163 
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;
168 	}
169 
170 	return OK;
171 }
172 
173 int
rtc_exit(void)174 rtc_exit(void)
175 {
176 	return OK;
177 }
178 
179 static int
bcd_to_dec(int n)180 bcd_to_dec(int n)
181 {
182 	return ((n >> 4) & 0x0F) * 10 + (n & 0x0F);
183 }
184 
185 static int
dec_to_bcd(int n)186 dec_to_bcd(int n)
187 {
188 	return ((n / 10) << 4) | (n % 10);
189 }
190