File indexing completed on 2025-05-11 08:24:05
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
0030
0031
0032
0033
0034
0035
0036 #include <dev/i2c/i2c.h>
0037 #include <libchip/i2c-rtc.h>
0038 #include <rtems/score/sysstate.h>
0039 #include <rtems/score/todimpl.h>
0040
0041 #include <fcntl.h>
0042 #include <string.h>
0043 #include <sys/stat.h>
0044 #include <unistd.h>
0045
0046 #define RTCSEC_SECBCD_SHIFT 0u
0047 #define RTCSEC_SECBCD_MASK (0x7fu << RTCSEC_SECBCD_SHIFT)
0048 #define RTCSEC_SECBCD(x) (((x) << RTCSEC_SECBCD_SHIFT) & RTCSEC_SECBCD_MASK)
0049 #define RTCSEC_SECBCD_GET(x) (((x) & RTCSEC_SECBCD_MASK) >> RTCSEC_SECBCD_SHIFT)
0050
0051 #define RTCMIN_MINBCD_SHIFT 0u
0052 #define RTCMIN_MINBCD_MASK (0x7fu << RTCMIN_MINBCD_SHIFT)
0053 #define RTCMIN_MINBCD(x) (((x) << RTCMIN_MINBCD_SHIFT) & RTCMIN_MINBCD_MASK)
0054 #define RTCMIN_MINBCD_GET(x) (((x) & RTCMIN_MINBCD_MASK) >> RTCMIN_MINBCD_SHIFT)
0055
0056 #define RTCHOUR_HRBCD12_SHIFT 0u
0057 #define RTCHOUR_HRBCD12_MASK (0x1fu << RTCHOUR_HRBCD12_SHIFT)
0058 #define RTCHOUR_HRBCD12(x) (((x) << RTCHOUR_HRBCD12_SHIFT) & RTCHOUR_HRBCD12_MASK)
0059 #define RTCHOUR_HRBCD12_GET(x) (((x) & RTCHOUR_HRBCD12_MASK) >> RTCHOUR_HRBCD12_SHIFT)
0060
0061 #define RTCHOUR_HRBCD24_SHIFT 0u
0062 #define RTCHOUR_HRBCD24_MASK (0x3fu << RTCHOUR_HRBCD24_SHIFT)
0063 #define RTCHOUR_HRBCD24(x) (((x) << RTCHOUR_HRBCD24_SHIFT) & RTCHOUR_HRBCD24_MASK)
0064 #define RTCHOUR_HRBCD24_GET(x) (((x) & RTCHOUR_HRBCD24_MASK) >> RTCHOUR_HRBCD24_SHIFT)
0065
0066 #define RTCHOUR_AMPM (0x01u << 5)
0067 #define RTCHOUR_1224 (0x01u << 6)
0068
0069 #define RTCWKDAY_WKDAY_SHIFT 0u
0070 #define RTCWKDAY_WKDAY_MASK (0x7u << RTCWKDAY_WKDAY_SHIFT)
0071 #define RTCWKDAY_WKDAY(x) (((x) << RTCWKDAY_WKDAY_SHIFT) & RTCWKDAY_WKDAY_MASK)
0072 #define RTCWKDAY_WKDAY_GET(x) (((x) & RTCWKDAY_WKDAY_MASK) >> RTCWKDAY_WKDAY_SHIFT)
0073
0074 #define RTCDATE_DATEBCD_SHIFT 0u
0075 #define RTCDATE_DATEBCD_MASK (0x3fu << RTCDATE_DATEBCD_SHIFT)
0076 #define RTCDATE_DATEBCD(x) (((x) << RTCDATE_DATEBCD_SHIFT) & RTCDATE_DATEBCD_MASK)
0077 #define RTCDATE_DATEBCD_GET(x) (((x) & RTCDATE_DATEBCD_MASK) >> RTCDATE_DATEBCD_SHIFT)
0078
0079 #define RTCMTH_MTHBCD_SHIFT 0u
0080 #define RTCMTH_MTHBCD_MASK (0x1fu << RTCMTH_MTHBCD_SHIFT)
0081 #define RTCMTH_MTHBCD(x) (((x) << RTCMTH_MTHBCD_SHIFT) & RTCMTH_MTHBCD_MASK)
0082 #define RTCMTH_MTHBCD_GET(x) (((x) & RTCMTH_MTHBCD_MASK) >> RTCMTH_MTHBCD_SHIFT)
0083
0084 #define RTCYEAR_YRBCD_SHIFT 0u
0085 #define RTCYEAR_YRBCD_MASK (0xffu << RTCYEAR_YRBCD_SHIFT)
0086 #define RTCYEAR_YRBCD(x) (((x) << RTCYEAR_YRBCD_SHIFT) & RTCYEAR_YRBCD_MASK)
0087 #define RTCYEAR_YRBCD_GET(x) (((x) & RTCYEAR_YRBCD_MASK) >> RTCYEAR_YRBCD_SHIFT)
0088
0089 #define NR_RTC_REGISTERS 0x07u
0090
0091 static inline uint8_t bcd_to_bin(uint8_t bcd)
0092 {
0093 uint8_t bin;
0094 bin = bcd & 0x0f;
0095 bin += ((bcd >> 4) & 0x0f) * 10;
0096 return bin;
0097 }
0098
0099 static inline uint8_t bin_to_bcd(uint8_t bin)
0100 {
0101 uint8_t bcd;
0102 bcd = bin % 10;
0103 bcd |= (bin / 10) << 4;
0104 return bcd;
0105 }
0106
0107 static struct i2c_rtc_base *i2c_rtc_get_context(int minor)
0108 {
0109 return (struct i2c_rtc_base *) RTC_Table[minor].pDeviceParams;
0110 }
0111
0112 int i2c_rtc_read(
0113 struct i2c_rtc_base *ctx,
0114 uint8_t addr,
0115 uint8_t *buf,
0116 size_t len
0117 )
0118 {
0119 int fd;
0120 int rv;
0121 struct i2c_msg msgs[] = {{
0122 .addr = ctx->i2c_addr,
0123 .flags = 0,
0124 .buf = &addr,
0125 .len = 1,
0126 }, {
0127 .addr = ctx->i2c_addr,
0128 .flags = I2C_M_RD,
0129 .buf = buf,
0130 .len = len,
0131 }};
0132 struct i2c_rdwr_ioctl_data payload = {
0133 .msgs = msgs,
0134 .nmsgs = sizeof(msgs)/sizeof(msgs[0]),
0135 };
0136
0137 fd = open(ctx->i2c_bus_path, O_RDWR);
0138 if (fd < 0) {
0139 return fd;
0140 }
0141
0142 rv = ioctl(fd, I2C_RDWR, &payload);
0143
0144 close(fd);
0145
0146 return rv;
0147 }
0148
0149 int i2c_rtc_write(
0150 struct i2c_rtc_base *ctx,
0151 uint8_t addr,
0152 const uint8_t *buf,
0153 size_t len
0154 )
0155 {
0156 int fd;
0157 int rv;
0158 uint8_t writebuf[len + 1];
0159 struct i2c_msg msgs[] = {{
0160 .addr = ctx->i2c_addr,
0161 .flags = 0,
0162 .buf = writebuf,
0163 .len = len + 1,
0164 }};
0165 struct i2c_rdwr_ioctl_data payload = {
0166 .msgs = msgs,
0167 .nmsgs = sizeof(msgs)/sizeof(msgs[0]),
0168 };
0169
0170 writebuf[0] = addr;
0171 memcpy(&writebuf[1], buf, len);
0172
0173 fd = open(ctx->i2c_bus_path, O_RDWR);
0174 if (fd < 0) {
0175 return fd;
0176 }
0177
0178 rv = ioctl(fd, I2C_RDWR, &payload);
0179
0180 close(fd);
0181
0182 return rv;
0183 }
0184
0185 static int i2c_rtc_initialize_once(struct i2c_rtc_base *ctx)
0186 {
0187 int rv;
0188
0189 if (ctx->initialized || ctx->hw_init == NULL) {
0190 return 0;
0191 }
0192
0193 rv = ctx->hw_init(ctx);
0194
0195 if (rv == 0) {
0196 ctx->initialized = true;
0197 }
0198
0199 return rv;
0200 }
0201
0202 static int i2c_rtc_get_time(int minor, rtems_time_of_day *time)
0203 {
0204 int rv = 0;
0205 uint8_t buf[NR_RTC_REGISTERS];
0206 struct i2c_rtc_base *ctx = i2c_rtc_get_context(minor);
0207
0208 if (!_System_state_Is_up(_System_state_Get())) {
0209 return -1;
0210 }
0211
0212 rtems_mutex_lock(&ctx->mutex);
0213
0214 rv = i2c_rtc_initialize_once(ctx);
0215
0216 if (rv == 0) {
0217 rv = i2c_rtc_read(ctx, ctx->clock_offset, buf, sizeof(buf));
0218 }
0219
0220 if (rv == 0) {
0221 unsigned year = bcd_to_bin(RTCYEAR_YRBCD_GET(buf[ctx->order.year])) +
0222 (TOD_BASE_YEAR / 100 * 100);
0223 if (year < TOD_BASE_YEAR) {
0224 year += 100;
0225 }
0226 time->year = year;
0227 time->month = bcd_to_bin(RTCMTH_MTHBCD_GET(buf[ctx->order.month]));
0228 time->day = bcd_to_bin(RTCDATE_DATEBCD_GET(buf[ctx->order.day]));
0229 time->hour = bcd_to_bin(RTCHOUR_HRBCD24_GET(buf[ctx->order.hour]));
0230 time->minute = bcd_to_bin(RTCMIN_MINBCD_GET(buf[ctx->order.min]));
0231 time->second = bcd_to_bin(RTCSEC_SECBCD_GET(buf[ctx->order.sec]));
0232 time->ticks = 0;
0233 }
0234
0235 rtems_mutex_unlock(&ctx->mutex);
0236
0237 return rv;
0238 }
0239
0240 static int i2c_rtc_set_time(int minor, const rtems_time_of_day *time)
0241 {
0242 int rv = 0;
0243 uint8_t buf[NR_RTC_REGISTERS];
0244 struct i2c_rtc_base *ctx = i2c_rtc_get_context(minor);
0245
0246 if (!_System_state_Is_up(_System_state_Get())) {
0247 return -1;
0248 }
0249
0250 rtems_mutex_lock(&ctx->mutex);
0251
0252 rv = i2c_rtc_initialize_once(ctx);
0253
0254 if (rv == 0) {
0255 rv = i2c_rtc_read(ctx, ctx->clock_offset, buf, sizeof(buf));
0256 }
0257
0258 if (rv == 0) {
0259
0260 if (RTCWKDAY_WKDAY_GET(buf[ctx->order.wkday]) < 1) {
0261 buf[ctx->order.wkday] &= ~RTCWKDAY_WKDAY_MASK;
0262 buf[ctx->order.wkday] |= RTCWKDAY_WKDAY(1);
0263 }
0264
0265 buf[ctx->order.year] &= ~RTCYEAR_YRBCD_MASK;
0266 buf[ctx->order.year] |= RTCYEAR_YRBCD(bin_to_bcd(time->year % 100));
0267
0268 buf[ctx->order.month] &= ~RTCMTH_MTHBCD_MASK;
0269 buf[ctx->order.month] |= RTCMTH_MTHBCD(bin_to_bcd(time->month));
0270
0271 buf[ctx->order.day] &= ~RTCDATE_DATEBCD_MASK;
0272 buf[ctx->order.day] |= RTCDATE_DATEBCD(bin_to_bcd(time->day));
0273
0274 buf[ctx->order.hour] &= ~(RTCHOUR_HRBCD24_MASK | RTCHOUR_1224);
0275 buf[ctx->order.hour] |= RTCHOUR_HRBCD24(bin_to_bcd(time->hour));
0276
0277 buf[ctx->order.min] &= ~RTCMIN_MINBCD_MASK;
0278 buf[ctx->order.min] |= RTCMIN_MINBCD(bin_to_bcd(time->minute));
0279
0280 buf[ctx->order.sec] &= ~RTCSEC_SECBCD_MASK;
0281 buf[ctx->order.sec] |= RTCSEC_SECBCD(bin_to_bcd(time->second));
0282
0283 rv = i2c_rtc_write(ctx, ctx->clock_offset, buf, sizeof(buf));
0284 }
0285
0286 rtems_mutex_unlock(&ctx->mutex);
0287
0288 return rv;
0289 }
0290
0291 static void i2c_rtc_init(int minor)
0292 {
0293 (void) minor;
0294 }
0295
0296 bool i2c_rtc_probe(int minor)
0297 {
0298 return true;
0299 }
0300
0301 const rtc_fns i2c_rtc_fns = {
0302 .deviceInitialize = i2c_rtc_init,
0303 .deviceGetTime = i2c_rtc_get_time,
0304 .deviceSetTime = i2c_rtc_set_time,
0305 };