summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu/bfin/clock/rtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libcpu/bfin/clock/rtc.c')
-rw-r--r--c/src/lib/libcpu/bfin/clock/rtc.c184
1 files changed, 184 insertions, 0 deletions
diff --git a/c/src/lib/libcpu/bfin/clock/rtc.c b/c/src/lib/libcpu/bfin/clock/rtc.c
new file mode 100644
index 0000000000..dace52eae2
--- /dev/null
+++ b/c/src/lib/libcpu/bfin/clock/rtc.c
@@ -0,0 +1,184 @@
+/* Real Time Clock Driver for Blackfin
+ *
+ * Copyright (c) 2006 by Atos Automacao Industrial Ltda.
+ * written by Alain Schaefer <alain.schaefer@easc.ch>
+ * and Antonio Giovanini <antonio@atos.com.br>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+
+#include <rtems.h>
+#include "tod.h"
+#include <rtems/libio.h>
+#include <rtems/score/tod.h>
+#include <rtems/rtems/types.h>
+#include <bsp.h>
+#include <libcpu/rtcRegs.h>
+
+/* The following are inside RTEMS -- we are violating visibility!!!
+ * Perhaps an API could be defined to get days since 1 Jan.
+ */
+extern const uint16_t _TOD_Days_to_date[2][13];
+
+/*
+ * Prototypes and routines used below
+ */
+int Leap_years_until_now (int year);
+
+void Init_RTC(void)
+{
+ *((uint16_t*)RTC_PREN) = RTC_PREN_PREN; /* Enable Prescaler */
+}
+
+rtems_device_driver rtc_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor_arg,
+ void *arg
+)
+{
+ rtems_status_code status;
+
+ /*
+ * Register and initialize the primary RTC's
+ */
+
+ status = rtems_io_register_name( "/dev/rtc", major, 0 );
+ if (status != RTEMS_SUCCESSFUL) {
+ rtems_fatal_error_occurred(status);
+ }
+
+ Init_RTC();
+
+ setRealTimeToRTEMS();
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Read time from RTEMS' clock manager and set it to RTC
+ */
+
+void setRealTimeFromRTEMS (void)
+{
+ rtems_time_of_day time_buffer;
+ rtems_status_code status;
+
+ status = rtems_clock_get( RTEMS_CLOCK_GET_TOD, &time_buffer );
+ if (status == RTEMS_SUCCESSFUL){
+ setRealTime(&time_buffer);
+ }
+}
+
+/*
+ * Read real time from RTC and set it to RTEMS' clock manager
+ */
+
+void setRealTimeToRTEMS (void)
+{
+ rtems_time_of_day time_buffer;
+
+ getRealTime(&time_buffer);
+ rtems_clock_set( &time_buffer );
+}
+
+ /*
+ * Set the RTC time
+ */
+int setRealTime(
+ rtems_time_of_day *tod
+)
+{
+ uint32_t days;
+ rtems_time_of_day tod_temp;
+
+ tod_temp = *tod;
+
+ days = (tod_temp.year - TOD_BASE_YEAR) * 365 + \
+ _TOD_Days_to_date[0][tod_temp.month] + tod_temp.day - 1;
+ if (tod_temp.month < 3)
+ days += Leap_years_until_now (tod_temp.year - 1);
+ else
+ days += Leap_years_until_now (tod_temp.year);
+
+ *((uint32_t volatile *)RTC_STAT) = (days << RTC_STAT_DAYS_SHIFT)|
+ (tod_temp.hour << RTC_STAT_HOURS_SHIFT)|
+ (tod_temp.minute << RTC_STAT_MINUTES_SHIFT)|
+ tod_temp.second;
+
+ return 0;
+}
+
+ /*
+ * Get the time from the RTC.
+ */
+
+void getRealTime(
+ rtems_time_of_day *tod
+)
+{
+ uint32_t days, rtc_reg;
+ rtems_time_of_day tod_temp;
+ int n, Leap_year;
+
+ rtc_reg = *((uint32_t volatile *)RTC_STAT);
+
+ days = (rtc_reg >> RTC_STAT_DAYS_SHIFT) + 1;
+
+ /* finding year */
+ tod_temp.year = days/365 + TOD_BASE_YEAR;
+ if (days%365 > Leap_years_until_now (tod_temp.year - 1)) {
+ days = (days%365) - Leap_years_until_now (tod_temp.year - 1);
+ } else {
+ tod_temp.year--;
+ days = (days%365) + 365 - Leap_years_until_now (tod_temp.year - 1);
+ }
+
+ /* finding month and day */
+ Leap_year = (((!(tod_temp.year%4)) && (tod_temp.year%100)) ||
+ (!(tod_temp.year%400)))?1:0;
+ for (n=1; n<=12; n++) {
+ if (days <= _TOD_Days_to_date[Leap_year][n+1]) {
+ tod_temp.month = n;
+ tod_temp.day = days - _TOD_Days_to_date[Leap_year][n];
+ break;
+ }
+ }
+
+ tod_temp.hour = (rtc_reg & RTC_STAT_HOURS_MASK) >> RTC_STAT_HOURS_SHIFT;
+ tod_temp.minute = (rtc_reg & RTC_STAT_MINUTES_MASK) >> RTC_STAT_MINUTES_SHIFT;
+ tod_temp.second = (rtc_reg & RTC_STAT_SECONDS_MASK);
+ tod_temp.ticks = 0;
+ *tod = tod_temp;
+}
+
+/*
+ * Return the difference between RTC and RTEMS' clock manager time in minutes.
+ * If the difference is greater than 1 day, this returns 9999.
+ */
+
+int checkRealTime (void)
+{
+ rtems_time_of_day rtems_tod;
+ rtems_time_of_day rtc_tod;
+ uint32_t rtems_time;
+ uint32_t rtc_time;
+
+ rtems_clock_get( RTEMS_CLOCK_GET_TOD, &rtems_tod );
+ getRealTime ( &rtc_tod );
+
+ rtems_time = _TOD_To_seconds( &rtems_tod );
+ rtc_time = _TOD_To_seconds( &rtc_tod );
+
+ return rtems_time - rtc_time;
+}
+
+int Leap_years_until_now (int year)
+{
+ return ((year/4 - year/100 + year/400) -
+ ((TOD_BASE_YEAR - 1)/4 - (TOD_BASE_YEAR - 1)/100 +
+ (TOD_BASE_YEAR - 1)/400));
+}