File indexing completed on 2025-05-11 08:23:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 #include <rtems.h>
0030 #include <bsp/fatal.h>
0031 #include <bsp/i2c.h>
0032 #include <libchip/rtc.h>
0033 #include <string.h>
0034 #include "pcf8563.h"
0035
0036
0037 #define From_BCD( _x ) ((((_x) >> 4) * 10) + ((_x) & 0x0F))
0038 #define To_BCD( _x ) ((((_x) / 10) << 4) + ((_x) % 10))
0039
0040
0041
0042
0043
0044
0045
0046
0047 static void
0048 pcf8563_initialize(int minor)
0049 {
0050 i2c_message_status status;
0051 int try;
0052 uint8_t ctrl1;
0053 i2c_bus_number bus;
0054 i2c_address addr;
0055
0056 bus = RTC_Table[minor].ulCtrlPort1;
0057 addr = RTC_Table[minor].ulDataPort;
0058
0059
0060 try = 0;
0061 do {
0062 status = i2c_wbrd(bus, addr, PCF8563_CONTROL1_ADR,
0063 &ctrl1, sizeof(ctrl1));
0064 try++;
0065 } while ((status != I2C_SUCCESSFUL) && (try < 15));
0066
0067
0068 if ((ctrl1 & PCF8563_CONTROL1_STOP) != 0)
0069 {
0070 uint8_t start[8];
0071 memset(start, 0, sizeof(start));
0072 start[0] = PCF8563_CONTROL1_ADR;
0073 try = 0;
0074 do {
0075 status = i2c_write(bus, addr, start, 2);
0076 } while ((status != I2C_SUCCESSFUL) && (try < 15));
0077 }
0078 }
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092 static int
0093 pcf8563_get_time(int minor, rtems_time_of_day *time)
0094 {
0095 i2c_bus_number bus;
0096 i2c_address addr;
0097 uint8_t info[10];
0098 uint32_t v1, v2;
0099 i2c_message_status status;
0100 int try;
0101
0102 if (time == NULL)
0103 return -1;
0104
0105 bus = RTC_Table[minor].ulCtrlPort1;
0106 addr = RTC_Table[minor].ulDataPort;
0107
0108 memset(time, 0, sizeof(rtems_time_of_day));
0109 try = 0;
0110 do {
0111 status = i2c_wbrd(bus, addr, PCF8563_SECOND_ADR, info, sizeof(info));
0112 try++;
0113 } while ((status != I2C_SUCCESSFUL) && (try < 10));
0114
0115 if (status != I2C_SUCCESSFUL)
0116 {
0117 return -1;
0118 }
0119
0120 v1 = info[PCF8563_YEAR_ADR-PCF8563_SECOND_ADR];
0121 v2 = From_BCD(v1);
0122 if ((info[PCF8563_MONTH_ADR-PCF8563_SECOND_ADR]
0123 & PCF8563_MONTH_CENTURY) == 0) {
0124 time->year = 1900 + v2;
0125 }
0126 else {
0127 time->year = 2000 + v2;
0128 }
0129
0130 v1 = info[PCF8563_MONTH_ADR-PCF8563_SECOND_ADR] & PCF8563_MONTH_MASK;
0131 time->month = From_BCD(v1);
0132
0133 v1 = info[PCF8563_DAY_ADR-PCF8563_SECOND_ADR] & PCF8563_DAY_MASK;
0134 time->day = From_BCD(v1);
0135
0136 v1 = info[PCF8563_HOUR_ADR-PCF8563_SECOND_ADR] & PCF8563_HOUR_MASK;
0137 time->hour = From_BCD(v1);
0138
0139 v1 = info[PCF8563_MINUTE_ADR-PCF8563_SECOND_ADR] & PCF8563_MINUTE_MASK;
0140 time->minute = From_BCD(v1);
0141
0142 v1 = info[PCF8563_SECOND_ADR-PCF8563_SECOND_ADR] & PCF8563_SECOND_MASK;
0143 time->second = From_BCD(v1);
0144
0145 return 0;
0146 }
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159 static int
0160 pcf8563_set_time(int minor, const rtems_time_of_day *time)
0161 {
0162 i2c_bus_number bus;
0163 i2c_address addr;
0164 uint8_t info[8];
0165 i2c_message_status status;
0166 int try;
0167
0168 if (time == NULL)
0169 return -1;
0170
0171 bus = RTC_Table[minor].ulCtrlPort1;
0172 addr = RTC_Table[minor].ulDataPort;
0173
0174 if ((time->year >= 2100) || (time->year < 1900)) {
0175 bsp_fatal(MPC5200_FATAL_PCF8563_INVALID_YEAR);
0176 }
0177 info[0] = PCF8563_SECOND_ADR;
0178 info[1 + PCF8563_YEAR_ADR -PCF8563_SECOND_ADR] = To_BCD(time->year % 100);
0179 info[1 + PCF8563_MONTH_ADR -PCF8563_SECOND_ADR] = To_BCD(time->month);
0180 info[1 + PCF8563_DAY_ADR -PCF8563_SECOND_ADR] = To_BCD(time->day);
0181 info[1 + PCF8563_HOUR_ADR -PCF8563_SECOND_ADR] = To_BCD(time->hour);
0182 info[1 + PCF8563_MINUTE_ADR-PCF8563_SECOND_ADR] = To_BCD(time->minute);
0183 info[1 + PCF8563_SECOND_ADR-PCF8563_SECOND_ADR] = To_BCD(time->second);
0184
0185 info[1 + PCF8563_DAY_OF_WEEK_ADR-PCF8563_SECOND_ADR] = 1;
0186
0187
0188
0189
0190 if (time->year >= 2000) {
0191 info[1 + PCF8563_MONTH_ADR -PCF8563_SECOND_ADR] |= PCF8563_MONTH_CENTURY;
0192 }
0193
0194
0195
0196 try = 0;
0197 do {
0198 status = i2c_write(bus, addr, info,sizeof(info));
0199 try++;
0200 } while ((status != I2C_SUCCESSFUL) && (try < 10));
0201
0202 if (status != I2C_SUCCESSFUL)
0203 return -1;
0204 else
0205 return 0;
0206 }
0207
0208
0209
0210 rtc_fns pcf8563_fns = {
0211 pcf8563_initialize,
0212 pcf8563_get_time,
0213 pcf8563_set_time
0214 };