Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:40

0001 /*
0002  * Real Time Clock Driver for Blackfin
0003  */
0004 
0005 /*
0006  *  Copyright (c) 2006 by Atos Automacao Industrial Ltda.
0007  *             written by Alain Schaefer <alain.schaefer@easc.ch>
0008  *                    and Antonio Giovanini <antonio@atos.com.br>
0009  *
0010  *  The license and distribution terms for this file may be
0011  *  found in the file LICENSE in this distribution or at
0012  *  http://www.rtems.org/license/LICENSE.
0013  */
0014 
0015 
0016 #include <rtems.h>
0017 #include <rtems/tod.h>
0018 #include <rtems/rtc.h>
0019 #include <rtems/libio.h>
0020 #include <bsp.h>
0021 #include <libcpu/rtcRegs.h>
0022 #include <rtems/score/todimpl.h>
0023 #include <rtems/rtems/clockimpl.h>
0024 
0025 /*
0026  *  Prototypes and routines used below
0027  */
0028 int Leap_years_until_now (int year);
0029 
0030 void Init_RTC(void)
0031 {
0032   *((uint16_t*)RTC_PREN) = RTC_PREN_PREN; /* Enable Prescaler */
0033 }
0034 
0035 /*
0036  *  Read time from RTEMS' clock manager and set it to RTC
0037  */
0038 void setRealTimeFromRTEMS (void)
0039 {
0040   rtems_time_of_day time_buffer;
0041   rtems_status_code status;
0042 
0043   status = rtems_clock_get_tod( &time_buffer );
0044   if (status == RTEMS_SUCCESSFUL){
0045     setRealTime(&time_buffer);
0046   }
0047 }
0048 
0049 /*
0050  *  Read real time from RTC and set it to RTEMS' clock manager
0051  */
0052 void setRealTimeToRTEMS (void)
0053 {
0054   rtems_time_of_day time_buffer;
0055 
0056   getRealTime(&time_buffer);
0057   rtems_clock_set( &time_buffer );
0058 }
0059 
0060 /*
0061  * Set the RTC time
0062  */
0063 int setRealTime(
0064   const rtems_time_of_day *tod
0065 )
0066 {
0067   uint32_t days;
0068   rtems_time_of_day tod_temp;
0069 
0070   tod_temp = *tod;
0071 
0072   days = (tod_temp.year - TOD_BASE_YEAR) * 365 + \
0073           _TOD_Days_to_date[1][tod_temp.month] + tod_temp.day - 1;
0074   if (tod_temp.month < 3)
0075     days +=  Leap_years_until_now (tod_temp.year - 1);
0076   else
0077     days +=  Leap_years_until_now (tod_temp.year);
0078 
0079   *((uint32_t volatile *)RTC_STAT) = (days << RTC_STAT_DAYS_SHIFT)|
0080                                      (tod_temp.hour << RTC_STAT_HOURS_SHIFT)|
0081                                      (tod_temp.minute << RTC_STAT_MINUTES_SHIFT)|
0082                                      tod_temp.second;
0083 
0084   return 0;
0085 }
0086 
0087 /*
0088  *  Get the time from the RTC.
0089  */
0090 void getRealTime(
0091   rtems_time_of_day *tod
0092 )
0093 {
0094   uint32_t days, rtc_reg;
0095   rtems_time_of_day tod_temp = { 0, 0, 0 };
0096   int n, Leap_year;
0097 
0098   rtc_reg = *((uint32_t volatile *)RTC_STAT);
0099 
0100   days = (rtc_reg >> RTC_STAT_DAYS_SHIFT) + 1;
0101 
0102   /* finding year */
0103   tod_temp.year = days/365 + TOD_BASE_YEAR;
0104   if (days%365 >  Leap_years_until_now (tod_temp.year - 1)) {
0105     days = (days%365) -  Leap_years_until_now (tod_temp.year - 1);
0106   } else {
0107     tod_temp.year--;
0108     days = (days%365) + 365 -  Leap_years_until_now (tod_temp.year - 1);
0109   }
0110 
0111   /* finding month and day */
0112   Leap_year = (((!(tod_temp.year%4)) && (tod_temp.year%100)) ||
0113               (!(tod_temp.year%400)))?0:1;
0114   for (n=1; n<=12; n++) {
0115     if (days <= _TOD_Days_to_date[Leap_year][n+1]) {
0116       tod_temp.month = n;
0117       tod_temp.day = days - _TOD_Days_to_date[Leap_year][n];
0118       break;
0119     }
0120   }
0121 
0122   tod_temp.hour  = (rtc_reg & RTC_STAT_HOURS_MASK) >> RTC_STAT_HOURS_SHIFT;
0123   tod_temp.minute  = (rtc_reg & RTC_STAT_MINUTES_MASK) >> RTC_STAT_MINUTES_SHIFT;
0124   tod_temp.second  = (rtc_reg & RTC_STAT_SECONDS_MASK);
0125   tod_temp.ticks = 0;
0126   *tod = tod_temp;
0127 }
0128 
0129 /*
0130  *  Return the difference between RTC and RTEMS' clock manager time in minutes.
0131  *  If the difference is greater than 1 day, this returns 9999.
0132  */
0133 int checkRealTime (void)
0134 {
0135   rtems_time_of_day rtems_tod;
0136   rtems_time_of_day rtc_tod;
0137   uint32_t   rtems_time;
0138   uint32_t   rtc_time;
0139 
0140   (void) rtems_clock_get_tod( &rtems_tod );
0141   getRealTime ( &rtc_tod );
0142 
0143   rtems_time = _TOD_To_seconds( &rtems_tod );
0144   rtc_time = _TOD_To_seconds( &rtc_tod );
0145 
0146   return rtems_time - rtc_time;
0147 }
0148 
0149 int Leap_years_until_now (int year)
0150 {
0151   return ((year/4 - year/100 + year/400) -
0152          ((TOD_BASE_YEAR - 1)/4 - (TOD_BASE_YEAR - 1)/100 +
0153           (TOD_BASE_YEAR - 1)/400));
0154 }
0155 
0156 rtems_device_driver rtc_initialize(
0157   rtems_device_major_number  major,
0158   rtems_device_minor_number  minor_arg,
0159   void                      *arg
0160 )
0161 {
0162   rtems_status_code          status;
0163 
0164   /*
0165    *  Register and initialize the primary RTC's
0166    */
0167 
0168   status = rtems_io_register_name( RTC_DEVICE_NAME, major, 0 );
0169   if (status != RTEMS_SUCCESSFUL) {
0170     rtems_fatal_error_occurred(status);
0171   }
0172 
0173   Init_RTC();
0174 
0175   setRealTimeToRTEMS();
0176   return RTEMS_SUCCESSFUL;
0177 }
0178 
0179 rtems_device_driver rtc_read(
0180   rtems_device_major_number  major,
0181   rtems_device_minor_number  minor,
0182   void *arg
0183 )
0184 {
0185   rtems_libio_rw_args_t *rw = arg;
0186   rtems_time_of_day *tod = (rtems_time_of_day *) rw->buffer;
0187 
0188   rw->offset = 0;
0189   rw->bytes_moved = 0;
0190 
0191   if (rw->count != sizeof( rtems_time_of_day)) {
0192     return RTEMS_INVALID_SIZE;
0193   }
0194 
0195   getRealTime( tod);
0196 
0197   rw->bytes_moved = rw->count;
0198 
0199   return RTEMS_SUCCESSFUL;
0200 }
0201 
0202 rtems_device_driver rtc_write(
0203   rtems_device_major_number  major,
0204   rtems_device_minor_number  minor,
0205   void *arg
0206 )
0207 {
0208   int rv = 0;
0209   rtems_libio_rw_args_t *rw = arg;
0210   const rtems_time_of_day *tod = (const rtems_time_of_day *) rw->buffer;
0211 
0212   rw->offset = 0;
0213   rw->bytes_moved = 0;
0214 
0215   if (rw->count != sizeof( rtems_time_of_day)) {
0216     return RTEMS_INVALID_SIZE;
0217   }
0218 
0219   rv = setRealTime( tod);
0220   if (rv != 0) {
0221     return RTEMS_IO_ERROR;
0222   }
0223 
0224   rw->bytes_moved = rw->count;
0225 
0226   return RTEMS_SUCCESSFUL;
0227 }
0228 
0229 rtems_device_driver rtc_open(
0230   rtems_device_major_number major,
0231   rtems_device_minor_number minor,
0232   void *arg
0233 )
0234 {
0235   return RTEMS_SUCCESSFUL;
0236 }
0237 
0238 rtems_device_driver rtc_close(
0239   rtems_device_major_number major,
0240   rtems_device_minor_number minor,
0241   void *arg
0242 )
0243 {
0244   return RTEMS_SUCCESSFUL;
0245 }
0246 
0247 rtems_device_driver rtc_control(
0248   rtems_device_major_number major,
0249   rtems_device_minor_number minor,
0250   void *arg
0251 )
0252 {
0253   return RTEMS_NOT_IMPLEMENTED;
0254 }