/* * Read time from chip */ int mc146818a_get_time( int minor, rtems_time_of_day *time ) { uint32_t mc146818a; getRegister_f getReg; uint32_t value; rtems_interrupt_level level; mc146818a = RTC_Table[ minor ].ulCtrlPort1; getReg = RTC_Table[ minor ].getRegister; /* * No time if power failed */ if (((*getReg)( mc146818a, MC146818A_STATUSD ) & MC146818ASD_PWR) == 0) return -1; /* * Wait for time update to complete */ rtems_interrupt_disable( level ); while (((*getReg)( mc146818a, MC146818A_STATUSA ) & MC146818ASA_TUP) != 0) { rtems_interrupt_flash( level ); } /* * Read the time (we have at least 244 usec to do this) */ value = (*getReg)( mc146818a, MC146818A_YEAR ); value = From_BCD( value ); if ( value < 88 ) time->year = 2000 + value; else time->year = 1900 + value; value = (*getReg)( mc146818a, MC146818A_MONTH ); time->month = From_BCD( value ); value = (*getReg)( mc146818a, MC146818A_DAY ); time->day = From_BCD( value ); value = (*getReg)( mc146818a, MC146818A_HRS ); time->hour = From_BCD( value ); value = (*getReg)( mc146818a, MC146818A_MIN ); time->minute = From_BCD( value ); value = (*getReg)( mc146818a, MC146818A_SEC ); rtems_interrupt_enable( level ); time->second = From_BCD( value ); time->ticks = 0; return 0; }
static int m48t08_get_time( int minor, rtems_time_of_day *time ) { uint32_t m48t08; getRegister_f getReg; setRegister_f setReg; uint8_t controlReg; uint32_t value1; uint32_t value2; m48t08 = RTC_Table[ minor ].ulCtrlPort1; getReg = RTC_Table[ minor ].getRegister; setReg = RTC_Table[ minor ].setRegister; /* * Put the RTC into read mode */ controlReg = (*getReg)( m48t08, M48T08_CONTROL ); (*setReg)( m48t08, M48T08_CONTROL, controlReg | M48T08_CONTROL_READ ); value1 = (*getReg)( m48t08, M48T08_YEAR ); value2 = From_BCD( value1 ); if ( value2 < 88 ) time->year = 2000 + value2; else time->year = 1900 + value2; value1 = (*getReg)( m48t08, M48T08_MONTH ); time->month = From_BCD( value1 ); value1 = (*getReg)( m48t08, M48T08_DATE ); time->day = From_BCD( value1 ); value1 = (*getReg)( m48t08, M48T08_HOUR ); time->hour = From_BCD( value1 ); value1 = (*getReg)( m48t08, M48T08_MINUTE ); time->minute = From_BCD( value1 ); value1 = (*getReg)( m48t08, M48T08_SECOND ); time->second = From_BCD( value1 ); time->ticks = 0; /* * Put the RTC back into normal mode. */ (*setReg)( m48t08, M48T08_CONTROL, controlReg ); return 0; }
/* ds1307_initialize -- * Initialize DS1307 real-time clock chip. If RTC is halted, this * function resume counting. * * PARAMETERS: * minor -- minor RTC device number */ void ds1307_initialize(int minor) { i2c_message_status status; int try; uint8_t sec; i2c_bus_number bus; i2c_address addr; bus = RTC_Table[minor].ulCtrlPort1; addr = RTC_Table[minor].ulDataPort; /* Read SECONDS register */ try = 0; do { status = i2c_wbrd(bus, addr, 0, &sec, sizeof(sec)); try++; } while ((status != I2C_SUCCESSFUL) && (try < 15)); /* If clock is halted, reset and start the clock */ if ((sec & DS1307_SECOND_HALT) != 0) { uint8_t start[8]; memset(start, 0, sizeof(start)); start[0] = DS1307_SECOND; try = 0; do { status = i2c_write(bus, addr, start, 2); } while ((status != I2C_SUCCESSFUL) && (try < 15)); } } /* ds1307_get_time -- * read current time from DS1307 real-time clock chip and convert it * to the rtems_time_of_day structure. * * PARAMETERS: * minor -- minor RTC device number * time -- place to put return value (date and time) * * RETURNS: * 0, if time obtained successfully * -1, if error occured */ int ds1307_get_time(int minor, rtems_time_of_day *time) { i2c_bus_number bus; i2c_address addr; uint8_t info[8]; uint32_t v1, v2; i2c_message_status status; int try; if (time == NULL) return -1; bus = RTC_Table[minor].ulCtrlPort1; addr = RTC_Table[minor].ulDataPort; memset(time, 0, sizeof(rtems_time_of_day)); try = 0; do { status = i2c_wbrd(bus, addr, 0, info, sizeof(info)); try++; } while ((status != I2C_SUCCESSFUL) && (try < 10)); if (status != I2C_SUCCESSFUL) { return -1; } v1 = info[DS1307_YEAR]; v2 = From_BCD(v1); if (v2 < 88) time->year = 2000 + v2; else time->year = 1900 + v2; v1 = info[DS1307_MONTH] & ~0xE0; time->month = From_BCD(v1); v1 = info[DS1307_DAY] & ~0xC0; time->day = From_BCD(v1); v1 = info[DS1307_HOUR]; if (v1 & DS1307_HOUR_12) { v2 = v1 & ~0xE0; if (v1 & DS1307_HOUR_PM) { time->hour = From_BCD(v2) + 12; } else { time->hour = From_BCD(v2); } } else { v2 = v1 & ~0xC0; time->hour = From_BCD(v2); } v1 = info[DS1307_MINUTE] & ~0x80; time->minute = From_BCD(v1); v1 = info[DS1307_SECOND]; v2 = v1 & ~0x80; time->second = From_BCD(v2); return 0; } /* ds1307_set_time -- * set time to the DS1307 real-time clock chip * * PARAMETERS: * minor -- minor RTC device number * time -- new date and time to be written to DS1307 * * RETURNS: * 0, if time obtained successfully * -1, if error occured */ int ds1307_set_time(int minor, const rtems_time_of_day *time) { i2c_bus_number bus; i2c_address addr; uint8_t info[8]; i2c_message_status status; int try; if (time == NULL) return -1; bus = RTC_Table[minor].ulCtrlPort1; addr = RTC_Table[minor].ulDataPort; if (time->year >= 2088) rtems_fatal_error_occurred(RTEMS_INVALID_NUMBER); info[0] = DS1307_SECOND; info[1 + DS1307_YEAR] = To_BCD(time->year % 100); info[1 + DS1307_MONTH] = To_BCD(time->month); info[1 + DS1307_DAY] = To_BCD(time->day); info[1 + DS1307_HOUR] = To_BCD(time->hour); info[1 + DS1307_MINUTE] = To_BCD(time->minute); info[1 + DS1307_SECOND] = To_BCD(time->second); info[1 + DS1307_DAY_OF_WEEK] = 1; /* Do not set day of week */ try = 0; do { status = i2c_write(bus, addr, info, 8); try++; } while ((status != I2C_SUCCESSFUL) && (try < 10)); if (status != I2C_SUCCESSFUL) return -1; else return 0; } /* Driver function table */ rtc_fns ds1307_fns = { ds1307_initialize, ds1307_get_time, ds1307_set_time };