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
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 #include <unistd.h> /* write, read, close */
0052
0053 #include <rtems.h>
0054 #include <rtems/bspIo.h>
0055 #include <rtems/rtc.h>
0056 #include <rtems/score/sysstate.h>
0057 #include <rtems/rtems/clockimpl.h>
0058 #include <libchip/rtc.h>
0059 #include <libchip/ds1375-rtc.h>
0060
0061 #include <sys/fcntl.h>
0062 #include <errno.h>
0063 #include <stdio.h>
0064 #include <string.h>
0065 #include <inttypes.h>
0066
0067
0068 #define STATIC static
0069 #undef DEBUG
0070
0071
0072
0073
0074
0075
0076
0077 #define STDIOSAFE(fmt,args...) \
0078 do { \
0079 if ( _System_state_Is_up( _System_state_Get() ) ) { \
0080 fprintf(stderr,fmt,args); \
0081 } else { \
0082 printk(fmt,args); \
0083 } \
0084 } while (0)
0085
0086
0087 STATIC uint8_t ds1375_bcd2bin(uint8_t x)
0088 {
0089 uint8_t h = x & 0xf0;
0090
0091
0092 return ( h >> 1 ) + ( h >> 3 ) + ( x & 0xf );
0093 }
0094
0095 STATIC uint8_t ds1375_bin2bcd(uint8_t x)
0096 {
0097 uint8_t h = x/10;
0098
0099 return ( h << 4 ) + ( x - ( ( h << 3 ) + ( h << 1 ) ) );
0100 }
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110 #define DS1375_SEC_REG 0x0
0111 #define DS1375_SEC_OFF (DS1375_SEC_REG-DS1375_SEC_REG)
0112
0113 #define DS1375_SEC(x) ds1375_bcd2bin( ((x)[DS1375_SEC_OFF]) & 0x7f )
0114
0115 #define DS1375_MIN_REG 0x1
0116 #define DS1375_MIN_OFF (DS1375_MIN_REG-DS1375_SEC_REG)
0117
0118 #define DS1375_MIN(x) ds1375_bcd2bin( ((x)[DS1375_MIN_OFF]) & 0x7f )
0119
0120 #define DS1375_HR_REG 0x2
0121 #define DS1375_HR_OFF (DS1375_HR_REG-DS1375_SEC_REG)
0122 #define DS1375_HR_1224 (1<<6)
0123 #define DS1375_HR_AMPM (1<<5)
0124
0125 #define DS1375_IS_AMPM(x) (DS1375_HR_1224 & ((x)[DS1375_HR_OFF]))
0126
0127 #define DS1375_IS_PM(x) (DS1375_HR_AMPM & ((x)[DS1375_HR_OFF]))
0128
0129 #define DS1375_HR_12(x) ds1375_bcd2bin( ((x)[DS1375_HR_OFF]) & 0x1f )
0130
0131 #define DS1375_HR_24(x) ds1375_bcd2bin( ((x)[DS1375_HR_OFF]) & 0x3f )
0132
0133 #define DS1375_DAY_REG 0x3
0134 #define DS1375_DAY_OFF (DS1375_DAY_REG-DS1375_SEC_REG)
0135 #define DS1375_DAT_REG 0x4
0136 #define DS1375_DAT_OFF (DS1375_DAT_REG-DS1375_SEC_REG)
0137
0138 #define DS1375_DAT(x) ds1375_bcd2bin( ((x)[DS1375_DAT_OFF]) & 0x3f )
0139 #define DS1375_MON_REG 0x5
0140 #define DS1375_MON_OFF (DS1375_MON_REG-DS1375_SEC_REG)
0141 #define DS1375_MON_CTRY (1<<7)
0142
0143 #define DS1375_IS_CTRY(x) (((x)[DS1375_MON_OFF]) & DS1375_MON_CTRY)
0144
0145 #define DS1375_MON(x) ds1375_bcd2bin( ((x)[DS1375_MON_OFF]) & 0x1f )
0146
0147 #define DS1375_YR_REG 0x6
0148 #define DS1375_YR_OFF (DS1375_YR_REG-DS1375_SEC_REG)
0149
0150 #define DS1375_YR(x) ds1375_bcd2bin( ((x)[DS1375_YR_OFF]) & 0xff )
0151
0152
0153 #define DS1375_CR_REG 0xe
0154 #define DS1375_CR_ECLK (1<<7)
0155 #define DS1375_CR_CLKSEL1 (1<<6)
0156 #define DS1375_CR_CLKSEL0 (1<<5)
0157 #define DS1375_CR_RS2 (1<<4)
0158 #define DS1375_CR_RS1 (1<<3)
0159 #define DS1375_CR_INTCN (1<<2)
0160 #define DS1375_CR_A2IE (1<<1)
0161 #define DS1375_CR_A1IE (1<<0)
0162
0163 #define DS1375_CSR_REG 0xf
0164
0165
0166 #define DS1375_RAM 0x10
0167
0168
0169
0170 STATIC int rd_bytes(
0171 int fd,
0172 uint32_t off,
0173 uint8_t *buf,
0174 int len
0175 )
0176 {
0177 uint8_t ptr = off;
0178
0179 return 1 == write( fd, &ptr, 1 ) && len == read( fd, buf, len ) ? 0 : -1;
0180 }
0181
0182 STATIC int wr_bytes(
0183 int fd,
0184 uint32_t off,
0185 uint8_t *buf,
0186 int len
0187 )
0188 {
0189 uint8_t d[ len + 1 ];
0190
0191
0192
0193
0194
0195
0196
0197
0198 d[0] = off;
0199 memcpy( d + 1, buf, len );
0200
0201 return len + 1 == write( fd, d, len + 1 ) ? 0 : -1;
0202 }
0203
0204
0205
0206 static int getfd(
0207 int minor
0208 )
0209 {
0210 return open( (const char *)RTC_Table[minor].ulCtrlPort1, O_RDWR );
0211 }
0212
0213
0214
0215 STATIC void ds1375_initialize(
0216 int minor
0217 )
0218 {
0219 int fd;
0220 uint8_t cr;
0221
0222 if ( ( fd = getfd( minor ) ) >= 0 ) {
0223 if ( 0 == rd_bytes( fd, DS1375_CR_REG, &cr, 1 ) ) {
0224
0225 if ( ! ( DS1375_CR_ECLK & cr ) ) {
0226 cr |= DS1375_CR_ECLK;
0227 wr_bytes( fd, DS1375_CR_REG, &cr, 1 );
0228 }
0229 }
0230 close( fd );
0231 }
0232
0233 }
0234
0235 STATIC int ds1375_get_time(
0236 int minor,
0237 rtems_time_of_day *time
0238 )
0239 {
0240 int rval = -1;
0241 int fd;
0242 uint8_t buf[DS1375_YR_REG + 1 - DS1375_SEC_REG];
0243
0244 if ( time && ( ( fd = getfd( minor ) ) >= 0 ) ) {
0245 if ( 0 == rd_bytes( fd, DS1375_SEC_REG, buf, sizeof(buf) ) ) {
0246 time->year = DS1375_IS_CTRY( buf ) ? 2000 : 1900;
0247 time->year += DS1375_YR ( buf );
0248 time->month = DS1375_MON( buf );
0249 time->day = DS1375_DAT( buf );
0250
0251 if ( DS1375_IS_AMPM( buf ) ) {
0252 time->hour = DS1375_HR_12 ( buf );
0253 if ( DS1375_IS_PM( buf ) )
0254 time->hour += 12;
0255 } else {
0256 time->hour = DS1375_HR_24 ( buf );
0257 }
0258
0259 time->minute = DS1375_MIN( buf );
0260 time->second = DS1375_SEC( buf );
0261 time->ticks = 0;
0262 rval = 0;
0263 }
0264 close( fd );
0265 }
0266 return rval;
0267 }
0268
0269 STATIC int ds1375_set_time(
0270 int minor,
0271 const rtems_time_of_day *time
0272 )
0273 {
0274 int rval = -1;
0275 int fd = -1;
0276 time_t secs;
0277 struct tm tm;
0278 uint8_t buf[DS1375_YR_REG + 1 - DS1375_SEC_REG];
0279 uint8_t cr = 0xff;
0280
0281
0282
0283
0284
0285
0286 secs = _TOD_To_seconds( time );
0287
0288 gmtime_r( &secs, &tm );
0289
0290 buf[DS1375_SEC_OFF] = ds1375_bin2bcd( time->second );
0291 buf[DS1375_MIN_OFF] = ds1375_bin2bcd( time->minute );
0292
0293 buf[DS1375_HR_OFF] = ds1375_bin2bcd( time->hour );
0294 buf[DS1375_DAY_OFF] = tm.tm_wday + 1;
0295 buf[DS1375_DAT_OFF] = ds1375_bin2bcd( time->day );
0296 buf[DS1375_MON_OFF] = ds1375_bin2bcd( time->month );
0297
0298 if ( time->year >= 2000 ) {
0299 buf[DS1375_YR_OFF] = ds1375_bin2bcd( time->year - 2000 );
0300 buf[DS1375_MON_OFF] |= DS1375_MON_CTRY;
0301 } else {
0302 buf[DS1375_YR_OFF] = ds1375_bin2bcd( time->year - 1900 );
0303 }
0304
0305
0306
0307
0308
0309
0310
0311
0312 if ( ( fd = getfd( minor ) ) < 0 ) {
0313 goto cleanup;
0314 }
0315
0316 if ( rd_bytes( fd, DS1375_CR_REG, &cr, 1 ) )
0317 goto cleanup;
0318
0319 cr &= ~DS1375_CR_ECLK;
0320
0321
0322 if ( wr_bytes( fd, DS1375_CR_REG, &cr, 1 ) )
0323 goto cleanup;
0324
0325
0326 if ( wr_bytes( fd, DS1375_SEC_REG, buf, sizeof(buf) ) )
0327 goto cleanup;
0328
0329 rval = 0;
0330
0331 cleanup:
0332 if ( fd >= 0 ) {
0333 if ( ! ( DS1375_CR_ECLK & cr ) ) {
0334
0335
0336
0337 cr |= DS1375_CR_ECLK;
0338 if ( wr_bytes( fd, DS1375_CR_REG, &cr, 1 ) )
0339 rval = -1;
0340 }
0341 close( fd );
0342 }
0343 return rval;
0344 }
0345
0346
0347
0348 #ifdef DEBUG
0349
0350
0351
0352
0353
0354 uint32_t
0355 ds1375_get_time_tst()
0356 {
0357 rtems_time_of_day rtod;
0358 time_t secs;
0359
0360 ds1375_get_time( 0, &rtod );
0361 secs = _TOD_To_seconds( &rtod );
0362 printf( "%s\n", ctime( &secs ) );
0363 return secs;
0364 }
0365
0366 int
0367 ds1375_set_time_tst( const char *datstr, rtems_time_of_day *prt )
0368 {
0369 struct tm tm;
0370 time_t secs;
0371 rtems_time_of_day rt;
0372
0373 if ( !datstr )
0374 return -1;
0375
0376 if ( ! strptime( datstr, "%Y-%m-%d/%T", &tm ) )
0377 return -2;
0378
0379 if ( ! prt )
0380 prt = &rt;
0381
0382 secs = mktime( &tm );
0383
0384
0385 gmtime_r( &secs, &tm );
0386
0387 printf("Y: %"PRIu32" ", (prt->year = tm.tm_year + 1900) );
0388 printf("M: %"PRIu32" ", (prt->month = tm.tm_mon + 1) );
0389 printf("D: %"PRIu32" ", (prt->day = tm.tm_mday ) );
0390 printf("h: %"PRIu32" ", (prt->hour = tm.tm_hour ) );
0391 printf("m: %"PRIu32" ", (prt->minute = tm.tm_min ) );
0392 printf("s: %"PRIu32"\n", (prt->second = tm.tm_sec ) );
0393 prt->ticks = 0;
0394
0395 return ( prt == &rt ) ? ds1375_set_time( 0, &rt ) : 0;
0396 }
0397
0398 #endif
0399
0400
0401 uint32_t
0402 rtc_ds1375_get_register( uintptr_t port, uint8_t reg )
0403 {
0404 int fd;
0405 uint8_t v;
0406 uint32_t rval = -1;
0407
0408 if ( ( fd = open( (const char*)port, O_RDWR ) ) >= 0 ) {
0409
0410 if ( 0 == rd_bytes( fd, reg, &v, 1 ) ) {
0411 rval = v;
0412 }
0413 close( fd );
0414 }
0415
0416 return rval;
0417 }
0418
0419 void
0420 rtc_ds1375_set_register( uintptr_t port, uint8_t reg, uint32_t value )
0421 {
0422 int fd;
0423 uint8_t v = value;
0424
0425 if ( ( fd = open( (const char*)port, O_RDWR ) ) >= 0 ) {
0426 wr_bytes( fd, reg, &v, 1 );
0427 close( fd );
0428 }
0429
0430 }
0431
0432 bool rtc_ds1375_device_probe(
0433 int minor
0434 )
0435 {
0436 int fd;
0437
0438 if ( ( fd = getfd( minor ) ) < 0 ) {
0439 STDIOSAFE( "ds1375_probe (open): %s\n", strerror( errno ) );
0440 return false;
0441 }
0442
0443
0444 if ( 0 != wr_bytes( fd, DS1375_SEC_REG, 0, 0 ) ) {
0445 STDIOSAFE( "ds1375_probe (wr_bytes): %s\n", strerror( errno ) );
0446 close( fd );
0447 return false;
0448 }
0449
0450 if ( close( fd ) ) {
0451 STDIOSAFE( "ds1375_probe (close): %s\n", strerror( errno ) );
0452 return false;
0453 }
0454
0455 return true;
0456 }
0457
0458 rtc_fns rtc_ds1375_fns = {
0459 .deviceInitialize = ds1375_initialize,
0460 .deviceGetTime = ds1375_get_time,
0461 .deviceSetTime = ds1375_set_time,
0462 };