1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
/*
* Date & Time support for Philips PCF8583 RTC
*/
#include "common.h"
#include <stdlib.h>
#include "debug.h"
#include "command.h"
#include "rtc.h"
#include "i2c.h"
#define DEBUG_RTC 0
#define debug_rtc(fmt, args...) \
debug_cond(DEBUG_RTC, fmt, ##args)
#define REG_CS 0x00 /* control/status */
#define REG_CSEC 0x01 /* hundredth of a second */
#define REG_SEC 0x02 /* seconds */
#define REG_MIN 0x03 /* minutes */
#define REG_HOUR 0x04 /* hours */
#define REG_YRDATE 0x05 /* year/date */
#define REG_WDMON 0x06 /* weekdays/months */
#define NR_OF_REGS 7
/* ------------------------------------------------------------------------- */
static uint_fast8_t bcd2bin(uint8_t val)
{
return (val >> 4) * 10 + (val & 0x0f);
}
static uint8_t bin2bcd (uint_fast8_t val)
{
div_t d = div(val, 10);
return (d.quot << 4) | d.rem;
}
int rtc_get (struct rtc_time *tmp)
{
int rel = 0;
uint8_t rtcbuf[NR_OF_REGS];
uint16_t year;
i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, rtcbuf, NR_OF_REGS);
i2c_read(CONFIG_SYS_I2C_RTC_ADDR, 0x10, 1, (uint8_t *) &year, 2);
debug_rtc("Get RTC year: %u, year/date: %02x, wdays/month: %02x, "
"hour: %02x, min: %02x, sec: %02x, (stat: %02x)\n", year,
rtcbuf[6], rtcbuf[5], rtcbuf[4], rtcbuf[3], rtcbuf[2], rtcbuf[0]);
tmp->tm_sec = bcd2bin (rtcbuf[REG_SEC] & 0x7F);
tmp->tm_min = bcd2bin (rtcbuf[REG_MIN] & 0x7F);
tmp->tm_hour = bcd2bin (rtcbuf[REG_HOUR] & 0x3F);
tmp->tm_mday = bcd2bin (rtcbuf[REG_YRDATE] & 0x3F);
tmp->tm_mon = bcd2bin (rtcbuf[REG_WDMON] & 0x1F);
while (year%4 < (rtcbuf[REG_YRDATE]>>6)) {
year++;
/* TODO: update RTC ram */
}
tmp->tm_year = year;
tmp->tm_wday = rtcbuf[REG_WDMON] >> 5;
tmp->tm_yday = 0;
tmp->tm_isdst= 0;
debug_rtc( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
return rel;
}
int rtc_set (struct rtc_time *tmp)
{
uint8_t rtcbuf[NR_OF_REGS];
debug_rtc("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
rtcbuf[REG_CS] = 0x84;
rtcbuf[REG_CSEC] = 0x00;
rtcbuf[REG_WDMON ] = bin2bcd(tmp->tm_mon) | ((tmp->tm_wday) << 5);
rtcbuf[REG_YRDATE] = ((tmp->tm_year % 4) << 6) | bin2bcd(tmp->tm_mday);
rtcbuf[REG_HOUR ] = bin2bcd(tmp->tm_hour);
rtcbuf[REG_MIN ] = bin2bcd(tmp->tm_min);
rtcbuf[REG_SEC ] = bin2bcd(tmp->tm_sec);
i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, rtcbuf, NR_OF_REGS);
i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0x10, 1, (uint8_t *) &tmp->tm_year, 2);
rtcbuf[REG_CS] = 0x04;
i2c_write(CONFIG_SYS_I2C_RTC_ADDR, 0, 1, rtcbuf, 1);
return 0;
}
|