Changeset a1d6f7a in rtems
- Timestamp:
- Apr 10, 2015, 6:23:00 AM (6 years ago)
- Branches:
- 4.11, 5, master
- Children:
- bcf536a
- Parents:
- a6c5a7e0
- git-author:
- Thomas Volgmann <Thomas.Volgmann@…> (04/10/15 06:23:00)
- git-committer:
- Sebastian Huber <sebastian.huber@…> (04/10/15 06:23:00)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
c/src/lib/libbsp/arm/altera-cyclone-v/rtc/rtc.c
ra6c5a7e0 ra1d6f7a 14 14 15 15 /* 16 * Driver for the DS1339 RTC. 16 * Driver for the DS1339 RTC (Maxim Semiconductors) -> RTC1 17 * and the M41ST87 RTC (ST Microelectronics) -> RTC2 17 18 * 18 19 * Please note the following points: … … 32 33 #include <bsp/i2cdrv.h> 33 34 34 #define ALTERA_CYCLONE_V_RTC_NUMBER 1 35 36 #define DS1339_I2C_ADDRESS 0x68 37 #define DS1339_I2C_BUS_DEVICE "/dev/i2c0" 38 39 #define DS1339_ADDR_CTRL 0x0E 40 #define DS1339_CTRL_EOSC 0x80 41 #define DS1339_CTRL_BBSQI 0x20 42 #define DS1339_CTRL_RS2 0x10 43 #define DS1339_CTRL_RS1 0x08 44 #define DS1339_CTRL_INTCN 0x04 45 #define DS1339_CTRL_A2IE 0x02 46 #define DS1339_CTRL_A1IE 0x01 47 48 #define DS1339_CTRL_DEFAULT (0x00) 49 50 #define DS1339_ADDR_TIME 0x00 51 #define DS1339_ADDR_STATUS 0x0F 52 #define DS1339_STATUS_OSF 0x80 53 #define DS1339_STATUS_A2F 0x02 54 #define DS1339_STATUS_A1F 0x01 55 56 #define DS1339_STATUS_CLEAR (0x00) 57 58 typedef struct { 59 uint8_t seconds; 60 uint8_t minutes; 61 uint8_t hours; 35 #define ALTERA_CYCLONE_V_RTC_NUMBER 2 36 37 38 /* ******************************* DS1339 ********************************** */ 39 40 41 #define DS1339_I2C_ADDRESS (0xD0 >> 1) /* 7-bit addressing! */ 42 #define DS1339_I2C_BUS_DEVICE "/dev/i2c0" 43 44 #define DS1339_ADDR_TIME 0x00 45 46 #define DS1339_ADDR_CTRL 0x0E 47 #define DS1339_CTRL_EOSC 0x80 48 #define DS1339_CTRL_BBSQI 0x20 49 #define DS1339_CTRL_RS2 0x10 50 #define DS1339_CTRL_RS1 0x08 51 #define DS1339_CTRL_INTCN 0x04 52 #define DS1339_CTRL_A2IE 0x02 53 #define DS1339_CTRL_A1IE 0x01 54 55 #define DS1339_CTRL_DEFAULT (0x00) 56 57 #define DS1339_ADDR_STATUS 0x0F 58 #define DS1339_STATUS_OSF 0x80 59 #define DS1339_STATUS_A2F 0x02 60 #define DS1339_STATUS_A1F 0x01 61 62 #define DS1339_STATUS_CLEAR (0x00) 63 64 #define DS1339_ADDR_TRICKLE_CHARGE 0x10 65 66 67 typedef struct 68 { 69 uint8_t seconds; 70 uint8_t minutes; 71 uint8_t hours; 62 72 #define DS1339_HOURS_12_24_FLAG 0x40 63 73 #define DS1339_HOURS_AM_PM_FLAG_OR_20_HOURS 0x20 64 74 #define DS1339_HOURS_10_HOURS 0x10 65 uint8_t weekday;66 uint8_t date;67 uint8_t month;75 uint8_t weekday; 76 uint8_t date; 77 uint8_t month; 68 78 #define DS1339_MONTH_CENTURY 0x80 69 uint8_t year; 70 } ds1339_time_t; 79 uint8_t year; 80 } 81 ds1339_time_t; 82 71 83 72 84 /* The longest write transmission is writing the time + one address bit */ 73 #define DS1339_MAX_WRITE_SIZE (sizeof(ds1339_time_t) + 1) 85 #define DS1339_MAX_WRITE_SIZE (sizeof(ds1339_time_t) + 1) 86 74 87 75 88 /* Functions for converting the fields */ 76 static unsigned int get_seconds (ds1339_time_t *time) { 77 uint8_t tens = time->seconds >> 4; 78 uint8_t ones = time->seconds & 0x0F; 79 return tens * 10 + ones; 80 } 81 82 static unsigned int get_minutes (ds1339_time_t *time) { 83 uint8_t tens = time->minutes >> 4; 84 uint8_t ones = time->minutes & 0x0F; 85 return tens * 10 + ones; 86 } 87 88 static unsigned int get_hours (ds1339_time_t *time) { 89 uint8_t value = time->hours & 0x0F; 90 91 if(time->hours & DS1339_HOURS_10_HOURS) { 89 static unsigned int ds1339_get_seconds(ds1339_time_t* time) 90 { 91 uint8_t tens = time->seconds >> 4; 92 uint8_t ones = time->seconds & 0x0F; 93 94 return tens * 10 + ones; 95 } 96 97 98 static unsigned int ds1339_get_minutes(ds1339_time_t* time) 99 { 100 uint8_t tens = time->minutes >> 4; 101 uint8_t ones = time->minutes & 0x0F; 102 103 return tens * 10 + ones; 104 } 105 106 107 static unsigned int ds1339_get_hours(ds1339_time_t* time) 108 { 109 110 uint8_t value = time->hours & 0x0F; 111 112 if (time->hours & DS1339_HOURS_10_HOURS) 113 { 92 114 value += 10; 93 115 } 94 if(time->hours & DS1339_HOURS_AM_PM_FLAG_OR_20_HOURS) { 95 if(time->hours & DS1339_HOURS_12_24_FLAG) { 116 if (time->hours & DS1339_HOURS_AM_PM_FLAG_OR_20_HOURS) 117 { 118 if (time->hours & DS1339_HOURS_12_24_FLAG) 96 119 value += 12; 97 } else {120 else 98 121 value += 20; 99 }100 122 } 101 123 … … 103 125 } 104 126 105 static unsigned int get_day_of_month (ds1339_time_t *time) { 106 uint8_t tens = time->date >> 4; 107 uint8_t ones = time->date & 0x0F; 108 return tens * 10 + ones; 109 } 110 111 static unsigned int get_month (ds1339_time_t *time) { 112 uint8_t tens = (time->month >> 4) & 0x07; 113 uint8_t ones = time->month & 0x0F; 114 return tens * 10 + ones; 115 } 116 117 static unsigned int get_year (ds1339_time_t *time) { 118 unsigned int year = 1900; 127 128 static unsigned int ds1339_get_day_of_month(ds1339_time_t* time) 129 { 130 131 uint8_t tens = time->date >> 4; 132 uint8_t ones = time->date & 0x0F; 133 134 return tens * 10 + ones; 135 } 136 137 138 static unsigned int ds1339_get_month(ds1339_time_t* time) 139 { 140 141 uint8_t tens = (time->month >> 4) & 0x07; 142 uint8_t ones = time->month & 0x0F; 143 144 return tens * 10 + ones; 145 } 146 147 148 static unsigned int ds1339_get_year(ds1339_time_t* time) 149 { 150 151 unsigned int year = 1900; 152 119 153 year += (time->year >> 4) * 10; 120 154 year += time->year & 0x0F; 121 if (time->month & DS1339_MONTH_CENTURY) {155 if (time->month & DS1339_MONTH_CENTURY) 122 156 year += 100; 123 } 124 if(year < TOD_BASE_YEAR) { 157 if (year < TOD_BASE_YEAR) 125 158 year += 200; 126 } 159 127 160 return year; 128 161 } 129 162 130 static void set_time ( 131 ds1339_time_t *time, 132 unsigned int second, 133 unsigned int minute, 134 unsigned int hour, 135 unsigned int day, 136 unsigned int month, 137 unsigned int year 138 ) { 139 unsigned int tens; 140 unsigned int ones; 141 uint8_t century = 0; 163 164 static void ds1339_set_time(ds1339_time_t* time, 165 unsigned int second, 166 unsigned int minute, 167 unsigned int hour, 168 unsigned int day, 169 unsigned int month, 170 unsigned int year) 171 { 172 173 unsigned int tens; 174 unsigned int ones; 175 uint8_t century = 0; 142 176 143 177 tens = second / 10; … … 162 196 tens = month / 10; 163 197 ones = month % 10; 164 if (year >= 2000 && year < 2100) {198 if ((year >= 2000) && (year < 2100)) 165 199 century = DS1339_MONTH_CENTURY; 166 }167 200 time->month = century | tens << 4 | ones; 168 201 … … 170 203 ones = year % 10; 171 204 time->year = tens << 4 | ones; 172 } 173 174 static rtems_status_code ds1339_open_file(int *fd) 175 { 176 int rv = 0; 177 rtems_status_code sc = RTEMS_SUCCESSFUL; 205 206 } 207 208 209 210 static rtems_status_code ds1339_open_file(int* fd) 211 { 212 213 int rv = 0; 214 rtems_status_code sc = RTEMS_SUCCESSFUL; 178 215 179 216 *fd = open(DS1339_I2C_BUS_DEVICE, O_RDWR); 180 if ( *fd == -1 ) {217 if (*fd == -1) 181 218 sc = RTEMS_IO_ERROR; 182 } 183 184 if ( sc == RTEMS_SUCCESSFUL ){219 220 if (sc == RTEMS_SUCCESSFUL) 221 { 185 222 rv = ioctl(*fd, I2C_IOC_SET_SLAVE_ADDRESS, DS1339_I2C_ADDRESS); 186 if ( rv == -1 ) {223 if (rv == -1) 187 224 sc = RTEMS_IO_ERROR; 188 }189 225 } 190 226 … … 192 228 } 193 229 230 194 231 /* Read size bytes from ds1339 register address addr to buf. */ 195 static rtems_status_code ds1339_read(uint8_t addr, void *buf, size_t size) 196 { 197 int fd = -1; 198 int rv = 0; 199 rtems_status_code sc = RTEMS_SUCCESSFUL; 232 static rtems_status_code ds1339_read(uint8_t addr, void* buf, size_t size) 233 { 234 235 int fd = -1; 236 int rv = 0; 237 rtems_status_code sc = RTEMS_SUCCESSFUL; 200 238 201 239 sc = ds1339_open_file(&fd); 202 240 203 if ( sc == RTEMS_SUCCESSFUL ) { 241 if (sc == RTEMS_SUCCESSFUL) 242 { 204 243 rv = write(fd, &addr, sizeof(addr)); 205 if ( rv != sizeof(addr) ) {244 if (rv != sizeof(addr)) 206 245 sc = RTEMS_IO_ERROR; 207 208 } 209 210 if ( sc == RTEMS_SUCCESSFUL ){246 } 247 248 if (sc == RTEMS_SUCCESSFUL) 249 { 211 250 rv = read(fd, buf, size); 212 if ( rv != size ) {251 if (rv != size) 213 252 sc = RTEMS_IO_ERROR; 214 }215 253 } 216 254 217 255 rv = close(fd); 218 if ( rv != 0 ) {256 if (rv != 0) 219 257 sc = RTEMS_IO_ERROR; 220 }221 258 222 259 return sc; 223 260 } 224 261 262 225 263 /* Write size bytes from buf to ds1339 register address addr. */ 226 static rtems_status_code ds1339_write(uint8_t addr, void *buf, size_t size) 227 { 228 int fd = -1; 229 int rv = 0; 230 rtems_status_code sc = RTEMS_SUCCESSFUL; 264 static rtems_status_code ds1339_write(uint8_t addr, void* buf, size_t size) 265 { 266 267 int fd = -1; 268 int rv = 0; 269 rtems_status_code sc = RTEMS_SUCCESSFUL; 231 270 /* The driver never writes many bytes. Therefore it should be less expensive 232 271 * to reserve the maximum number of bytes that will be written in one go than 233 272 * use a malloc. */ 234 uint8_t local_buf[DS1339_MAX_WRITE_SIZE];235 int write_size = size + 1;273 uint8_t local_buf[DS1339_MAX_WRITE_SIZE]; 274 int write_size = size + 1; 236 275 237 276 assert(write_size <= DS1339_MAX_WRITE_SIZE); … … 242 281 sc = ds1339_open_file(&fd); 243 282 244 if ( sc == RTEMS_SUCCESSFUL ) { 283 if (sc == RTEMS_SUCCESSFUL) 284 { 245 285 rv = write(fd, local_buf, write_size); 246 if ( rv != write_size ) {286 if (rv != write_size) 247 287 sc = RTEMS_IO_ERROR; 248 }249 288 } 250 289 251 290 rv = close(fd); 252 if ( rv != 0 ) {291 if (rv != 0) 253 292 sc = RTEMS_IO_ERROR; 254 }255 293 256 294 return RTEMS_SUCCESSFUL; 257 295 } 258 296 259 static void altera_cyclone_v_rtc_initialize(int minor) 260 { 261 rtems_status_code sc = RTEMS_SUCCESSFUL; 262 uint8_t status = 0; 297 298 static void altera_cyclone_v_ds1339_initialize(int minor) 299 { 300 301 rtems_status_code sc = RTEMS_SUCCESSFUL; 302 uint8_t status = 0; 263 303 264 304 /* Check RTC valid */ 265 305 sc = ds1339_read(DS1339_ADDR_STATUS, &status, sizeof(status)); 266 306 assert(sc == RTEMS_SUCCESSFUL); 267 if(status & DS1339_STATUS_OSF) { 307 308 if (status & DS1339_STATUS_OSF) 309 { 268 310 /* RTC has been stopped. Initialise it. */ 269 311 ds1339_time_t time; 270 312 271 uint8_t write = DS1339_CTRL_DEFAULT;313 uint8_t write = DS1339_CTRL_DEFAULT; 272 314 sc = ds1339_write(DS1339_ADDR_CTRL, &write, sizeof(write)); 273 315 assert(sc == RTEMS_SUCCESSFUL); … … 277 319 assert(sc == RTEMS_SUCCESSFUL); 278 320 279 set_time(&time, 0, 0, 0, 1, 1, TOD_BASE_YEAR);321 ds1339_set_time(&time, 0, 0, 0, 1, 1, TOD_BASE_YEAR); 280 322 sc = ds1339_write(DS1339_ADDR_TIME, &time, sizeof(time)); 281 323 assert(sc == RTEMS_SUCCESSFUL); 282 324 } 283 } 284 285 static int altera_cyclone_v_rtc_get_time(int minor, rtems_time_of_day *tod) 286 { 287 ds1339_time_t time; 288 rtems_status_code sc = RTEMS_SUCCESSFUL; 289 rtems_time_of_day temp_tod; 325 326 } 327 328 329 static int altera_cyclone_v_ds1339_get_time(int minor, rtems_time_of_day* tod) 330 { 331 332 ds1339_time_t time; 333 rtems_status_code sc = RTEMS_SUCCESSFUL; 334 rtems_time_of_day temp_tod; 290 335 291 336 sc = ds1339_read(DS1339_ADDR_TIME, &time, sizeof(time)); 292 337 293 if ( sc == RTEMS_SUCCESSFUL ) { 294 temp_tod.ticks = 0; 295 temp_tod.second = get_seconds(&time); 296 temp_tod.minute = get_minutes(&time); 297 temp_tod.hour = get_hours(&time); 298 temp_tod.day = get_day_of_month(&time); 299 temp_tod.month = get_month(&time); 300 temp_tod.year = get_year(&time); 301 302 if ( _TOD_Validate(&temp_tod) ) { 338 if (sc == RTEMS_SUCCESSFUL) 339 { 340 temp_tod.ticks = 0; 341 temp_tod.second = ds1339_get_seconds(&time); 342 temp_tod.minute = ds1339_get_minutes(&time); 343 temp_tod.hour = ds1339_get_hours(&time); 344 temp_tod.day = ds1339_get_day_of_month(&time); 345 temp_tod.month = ds1339_get_month(&time); 346 temp_tod.year = ds1339_get_year(&time); 347 348 if (_TOD_Validate(&temp_tod)) 303 349 memcpy(tod, &temp_tod, sizeof(temp_tod)); 304 } else {350 else 305 351 sc = RTEMS_INVALID_CLOCK; 306 }307 352 } 308 353 … … 310 355 } 311 356 312 static int altera_cyclone_v_rtc_set_time(int minor, const rtems_time_of_day *tod) 313 { 314 ds1339_time_t time; 315 rtems_status_code sc = RTEMS_SUCCESSFUL; 316 317 set_time ( 318 &time, 319 tod->second, 320 tod->minute, 321 tod->hour, 322 tod->day, 323 tod->month, 324 tod->year 325 ); 357 358 static int altera_cyclone_v_ds1339_set_time(int minor, const rtems_time_of_day* tod) 359 { 360 361 ds1339_time_t time; 362 rtems_status_code sc = RTEMS_SUCCESSFUL; 363 364 ds1339_set_time(&time, 365 tod->second, 366 tod->minute, 367 tod->hour, 368 tod->day, 369 tod->month, 370 tod->year 371 ); 326 372 327 373 sc = ds1339_write(DS1339_ADDR_TIME, &time, sizeof(time)); … … 330 376 } 331 377 332 static bool altera_cyclone_v_rtc_probe(int minor) 333 { 334 /* FIXME: Probe for i2c device */ 378 379 static bool altera_cyclone_v_ds1339_probe(int minor) 380 { 381 382 rtems_status_code sc = RTEMS_SUCCESSFUL; 383 uint8_t buf; 384 385 /* try to read from register address 0x00 */ 386 sc = ds1339_read(0x00, &buf, 1); 387 if (sc != RTEMS_SUCCESSFUL) 388 /* no RTC implemented */ 389 return false; 390 /* try to read from register address 0x20 (not implemented in DS1339) */ 391 sc = ds1339_read(0x20, &buf, 1); 392 if (sc == RTEMS_SUCCESSFUL) 393 /* RTC is not DS1339 */ 394 return false; 395 396 printk("RTC detected, type = DS1339\n"); 335 397 return true; 336 } 337 338 const rtc_fns altera_cyclone_v_rtc_ops = { 339 .deviceInitialize = altera_cyclone_v_rtc_initialize, 340 .deviceGetTime = altera_cyclone_v_rtc_get_time, 341 .deviceSetTime = altera_cyclone_v_rtc_set_time 398 399 } 400 401 402 /* ******************************* M41ST87 ********************************** */ 403 404 405 #define M41ST87_I2C_ADDRESS (0xD0 >> 1) /* 7-bit addressing! */ 406 #define M41ST87_I2C_BUS_DEVICE "/dev/i2c0" 407 408 #define M41ST87_ADDR_TIME 0x00 409 410 #define M41ST87_ADDR_CTRL 0x08 411 #define M41ST87_CTRL_OUT 0x80 412 #define M41ST87_CTRL_FT 0x40 413 #define M41ST87_CTRL_S 0x20 414 #define M41ST87_CTRL_CAL 0x1F 415 416 #define M41ST87_ADDR_ALARM_HOUR 0x0C 417 #define M41ST87_BIT_HT 0x40 418 419 #define M41ST87_ADDR_FLAGS 0x0F 420 #define M41ST87_FLAG_WDF 0x80 421 #define M41ST87_FLAG_AF 0x40 422 #define M41ST87_FLAG_BL 0x10 423 #define M41ST87_FLAG_OF 0x04 424 #define M41ST87_FLAG_TB1 0x02 425 #define M41ST87_FLAG_TB2 0x01 426 427 #define M41ST87_ADDR_USER_RAM 0x20 428 429 430 typedef struct 431 { 432 uint8_t sec100; 433 uint8_t seconds; 434 #define M41ST87_BIT_ST 0x80 435 uint8_t minutes; 436 #define M41ST87_BIT_OFIE 0x80 437 uint8_t hours; 438 #define M41ST87_BIT_CB1 0x80 439 #define M41ST87_BIT_CB0 0x40 440 uint8_t weekday; 441 #define M41ST87_BIT_TR 0x80 442 #define M41ST87_BIT_THS 0x40 443 #define M41ST87_BIT_CLRPW1 0x20 444 #define M41ST87_BIT_CLRPW0 0x10 445 #define M41ST87_BIT_32KE 0x08 446 uint8_t day; 447 #define M41ST87_BIT_PFOD 0x80 448 uint8_t month; 449 uint8_t year; 450 } 451 m41st87_time_t; 452 453 454 /* The longest write transmission is writing the time + one address bit */ 455 #define M41ST87_MAX_WRITE_SIZE (sizeof(m41st87_time_t) + 1) 456 457 458 /* Functions for converting the fields */ 459 460 /* 461 static unsigned int m41st87_get_sec100(m41st87_time_t* time) 462 { 463 464 uint8_t tens = time->sec100 >> 4; 465 uint8_t ones = time->sec100 & 0x0F; 466 467 return tens * 10 + ones; 468 } 469 */ 470 471 472 static unsigned int m41st87_get_seconds(m41st87_time_t* time) 473 { 474 475 uint8_t tens = (time->seconds >> 4) & 0x07; 476 uint8_t ones = time->seconds & 0x0F; 477 478 return tens * 10 + ones; 479 } 480 481 482 static unsigned int m41st87_get_minutes(m41st87_time_t* time) 483 { 484 485 uint8_t tens = (time->minutes >> 4) & 0x07; 486 uint8_t ones = time->minutes & 0x0F; 487 488 return tens * 10 + ones; 489 } 490 491 492 static unsigned int m41st87_get_hours(m41st87_time_t* time) 493 { 494 495 uint8_t tens = (time->hours >> 4) & 0x03; 496 uint8_t ones = time->hours & 0x0F; 497 498 return tens * 10 + ones; 499 } 500 501 502 /* 503 static unsigned int m41st87_get_day_of_week(m41st87_time_t* time) 504 { 505 506 return time->weekday & 0x07; 507 } 508 */ 509 510 511 static unsigned int m41st87_get_day_of_month(m41st87_time_t* time) 512 { 513 514 uint8_t tens = (time->day >> 4) & 0x03; 515 uint8_t ones = time->day & 0x0F; 516 517 return tens * 10 + ones; 518 } 519 520 521 static unsigned int m41st87_get_month(m41st87_time_t* time) 522 { 523 524 uint8_t tens = (time->month >> 4) & 0x01; 525 uint8_t ones = time->month & 0x0F; 526 527 return tens * 10 + ones; 528 } 529 530 531 static unsigned int m41st87_get_year(m41st87_time_t* time) 532 { 533 534 uint8_t century = time->hours >> 6; 535 uint8_t tens = time->year >> 4; 536 uint8_t ones = time->year & 0x0F; 537 538 return 1900 + century * 100 + tens * 10 + ones; 539 } 540 541 542 static void m41st87_set_time(m41st87_time_t* time, 543 unsigned int second, 544 unsigned int minute, 545 unsigned int hour, 546 unsigned int day, 547 unsigned int month, 548 unsigned int year) 549 { 550 551 unsigned int century; 552 unsigned int tens; 553 unsigned int ones; 554 555 if (year < 1900) 556 year = 1900; 557 if (year > 2399) 558 year = 2399; 559 century = (year - 1900) / 100; 560 561 /* Hundreds of seconds is not used, set to 0 */ 562 time->sec100 = 0; 563 564 tens = second / 10; 565 ones = second % 10; 566 time->seconds = (time->seconds & 0x80) | (tens << 4) | ones; 567 568 tens = minute / 10; 569 ones = minute % 10; 570 time->minutes = (time->minutes & 0x80) | (tens << 4) | ones; 571 572 tens = hour / 10; 573 ones = hour % 10; 574 time->hours = (century << 6) | (tens << 4) | ones; 575 576 /* Weekday is not used. Therefore it can be set to an arbitrary valid value */ 577 time->weekday = (time->weekday & 0xF8) | 1; 578 579 tens = day / 10; 580 ones = day % 10; 581 time->day = (time->day & 0x80) | (tens << 4) | ones; 582 583 tens = month / 10; 584 ones = month % 10; 585 time->month = (tens << 4) | ones; 586 587 tens = (year % 100) / 10; 588 ones = year % 10; 589 time->year = (tens << 4) | ones; 590 591 } 592 593 594 595 static rtems_status_code m41st87_open_file(int* fd) 596 { 597 598 int rv = 0; 599 rtems_status_code sc = RTEMS_SUCCESSFUL; 600 601 *fd = open(M41ST87_I2C_BUS_DEVICE, O_RDWR); 602 if (*fd == -1) 603 sc = RTEMS_IO_ERROR; 604 605 if (sc == RTEMS_SUCCESSFUL) 606 { 607 rv = ioctl(*fd, I2C_IOC_SET_SLAVE_ADDRESS, M41ST87_I2C_ADDRESS); 608 if (rv == -1) 609 sc = RTEMS_IO_ERROR; 610 } 611 612 return sc; 613 } 614 615 616 /* Read size bytes from m41st87 register address addr to buf. */ 617 static rtems_status_code m41st87_read(uint8_t addr, void* buf, size_t size) 618 { 619 620 int fd = -1; 621 int rv = 0; 622 rtems_status_code sc = RTEMS_SUCCESSFUL; 623 624 sc = m41st87_open_file(&fd); 625 626 if (sc == RTEMS_SUCCESSFUL) 627 { 628 rv = write(fd, &addr, sizeof(addr)); 629 if (rv != sizeof(addr)) 630 sc = RTEMS_IO_ERROR; 631 } 632 633 if (sc == RTEMS_SUCCESSFUL) 634 { 635 rv = read(fd, buf, size); 636 if (rv != size) 637 sc = RTEMS_IO_ERROR; 638 } 639 640 rv = close(fd); 641 if (rv != 0) 642 sc = RTEMS_IO_ERROR; 643 644 return sc; 645 } 646 647 648 /* Write size bytes from buf to m41st87 register address addr. */ 649 static rtems_status_code m41st87_write(uint8_t addr, void* buf, size_t size) 650 { 651 652 int fd = -1; 653 int rv = 0; 654 rtems_status_code sc = RTEMS_SUCCESSFUL; 655 /* The driver never writes many bytes. Therefore it should be less expensive 656 * to reserve the maximum number of bytes that will be written in one go than 657 * use a malloc. */ 658 uint8_t local_buf[M41ST87_MAX_WRITE_SIZE]; 659 int write_size = size + 1; 660 661 assert(write_size <= M41ST87_MAX_WRITE_SIZE); 662 663 local_buf[0] = addr; 664 memcpy(&local_buf[1], buf, size); 665 666 sc = m41st87_open_file(&fd); 667 668 if (sc == RTEMS_SUCCESSFUL) 669 { 670 rv = write(fd, local_buf, write_size); 671 if (rv != write_size) 672 sc = RTEMS_IO_ERROR; 673 } 674 675 rv = close(fd); 676 if (rv != 0) 677 sc = RTEMS_IO_ERROR; 678 679 return RTEMS_SUCCESSFUL; 680 } 681 682 683 static void altera_cyclone_v_m41st87_initialize(int minor) 684 { 685 686 m41st87_time_t time; 687 rtems_status_code sc = RTEMS_SUCCESSFUL; 688 uint8_t value; 689 690 /* Check RTC valid */ 691 sc = m41st87_read(M41ST87_ADDR_TIME, &time, sizeof(time)); 692 assert(sc == RTEMS_SUCCESSFUL); 693 694 if (time.seconds & M41ST87_BIT_ST) 695 { 696 /* RTC has been stopped. Reset stop flag. */ 697 time.seconds = 0; 698 /* Initialise RTC. */ 699 m41st87_set_time(&time, 0, 0, 0, 1, 1, TOD_BASE_YEAR); 700 sc = m41st87_write(M41ST87_ADDR_TIME, &time, sizeof(time)); 701 assert(sc == RTEMS_SUCCESSFUL); 702 } 703 704 /* Reset HT bit */ 705 sc = m41st87_read(M41ST87_ADDR_ALARM_HOUR, &value, 1); 706 assert(sc == RTEMS_SUCCESSFUL); 707 value &= ~M41ST87_BIT_HT; 708 sc = m41st87_write(M41ST87_ADDR_ALARM_HOUR, &value, 1); 709 assert(sc == RTEMS_SUCCESSFUL); 710 711 } 712 713 714 static int altera_cyclone_v_m41st87_get_time(int minor, rtems_time_of_day* tod) 715 { 716 717 m41st87_time_t time; 718 rtems_status_code sc = RTEMS_SUCCESSFUL; 719 rtems_time_of_day temp_tod; 720 721 sc = m41st87_read(M41ST87_ADDR_TIME, &time, sizeof(time)); 722 if (sc != RTEMS_SUCCESSFUL) 723 return -sc; 724 725 temp_tod.ticks = 0; 726 temp_tod.second = m41st87_get_seconds(&time); 727 temp_tod.minute = m41st87_get_minutes(&time); 728 temp_tod.hour = m41st87_get_hours(&time); 729 temp_tod.day = m41st87_get_day_of_month(&time); 730 temp_tod.month = m41st87_get_month(&time); 731 temp_tod.year = m41st87_get_year(&time); 732 733 if (_TOD_Validate(&temp_tod)) 734 memcpy(tod, &temp_tod, sizeof(temp_tod)); 735 else 736 sc = RTEMS_INVALID_CLOCK; 737 738 return -sc; 739 } 740 741 742 static int altera_cyclone_v_m41st87_set_time(int minor, const rtems_time_of_day* tod) 743 { 744 745 m41st87_time_t time; 746 rtems_status_code sc = RTEMS_SUCCESSFUL; 747 748 /* first read to preserve the additional flags */ 749 sc = m41st87_read(M41ST87_ADDR_TIME, &time, sizeof(time)); 750 if (sc != RTEMS_SUCCESSFUL) 751 return -sc; 752 753 m41st87_set_time(&time, 754 tod->second, 755 tod->minute, 756 tod->hour, 757 tod->day, 758 tod->month, 759 tod->year 760 ); 761 762 sc = m41st87_write(M41ST87_ADDR_TIME, &time, sizeof(time)); 763 764 return -sc; 765 } 766 767 768 static bool altera_cyclone_v_m41st87_probe(int minor) 769 { 770 771 rtems_status_code sc = RTEMS_SUCCESSFUL; 772 uint8_t buf; 773 774 /* try to read from register address 0x00 */ 775 sc = m41st87_read(0x00, &buf, 1); 776 if (sc != RTEMS_SUCCESSFUL) 777 /* no RTC implemented */ 778 return false; 779 /* try to read from register address 0x20 (implemented in M41ST87) */ 780 sc = m41st87_read(0x20, &buf, 1); 781 if (sc != RTEMS_SUCCESSFUL) 782 /* RTC is not M41ST87 */ 783 return false; 784 785 printk("RTC detected, type = M41ST87\n"); 786 return true; 787 788 } 789 790 791 /* **************************************** General ********************************** */ 792 793 794 const rtc_fns altera_cyclone_v_ds1339_ops = 795 { 796 .deviceInitialize = altera_cyclone_v_ds1339_initialize, 797 .deviceGetTime = altera_cyclone_v_ds1339_get_time, 798 .deviceSetTime = altera_cyclone_v_ds1339_set_time 342 799 }; 343 800 344 size_t RTC_Count = ALTERA_CYCLONE_V_RTC_NUMBER; 345 346 rtems_device_minor_number RTC_Minor = 0; 347 348 rtc_tbl RTC_Table [ALTERA_CYCLONE_V_RTC_NUMBER] = { 801 802 const rtc_fns altera_cyclone_v_m41st87_ops = 803 { 804 .deviceInitialize = altera_cyclone_v_m41st87_initialize, 805 .deviceGetTime = altera_cyclone_v_m41st87_get_time, 806 .deviceSetTime = altera_cyclone_v_m41st87_set_time 807 }; 808 809 810 size_t RTC_Count = ALTERA_CYCLONE_V_RTC_NUMBER; 811 rtems_device_minor_number RTC_Minor = 0; 812 813 814 rtc_tbl RTC_Table[ALTERA_CYCLONE_V_RTC_NUMBER] = 815 { 349 816 { 350 817 .sDeviceName = "/dev/rtc", 351 818 .deviceType = RTC_CUSTOM, 352 .pDeviceFns = &altera_cyclone_v_ rtc_ops,353 .deviceProbe = altera_cyclone_v_ rtc_probe,819 .pDeviceFns = &altera_cyclone_v_ds1339_ops, 820 .deviceProbe = altera_cyclone_v_ds1339_probe, 354 821 .pDeviceParams = NULL, 355 822 .ulCtrlPort1 = 0, … … 357 824 .getRegister = NULL, 358 825 .setRegister = NULL 826 }, 827 { 828 .sDeviceName = "/dev/rtc", 829 .deviceType = RTC_CUSTOM, 830 .pDeviceFns = &altera_cyclone_v_m41st87_ops, 831 .deviceProbe = altera_cyclone_v_m41st87_probe, 832 .pDeviceParams = NULL, 833 .ulCtrlPort1 = 0, 834 .ulDataPort = 0, 835 .getRegister = NULL, 836 .setRegister = NULL 359 837 } 360 838 };
Note: See TracChangeset
for help on using the changeset viewer.