Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:05

0001 /*
0002  *  Real Time Clock Driver Wrapper for Libchip
0003  */
0004 
0005 /*
0006  *  The license and distribution terms for this file may be
0007  *  found in the file LICENSE in this distribution or at
0008  *  http://www.rtems.org/license/LICENSE.
0009  */
0010 
0011 #include <rtems.h>
0012 #include <rtems/rtc.h>
0013 #include <rtems/tod.h>
0014 #include <rtems/libio.h>
0015 #include <rtems/rtems/clockimpl.h>
0016 
0017 #include <libchip/rtc.h>
0018 
0019 /*
0020  *  Configuration Information
0021  */
0022 static rtems_device_minor_number RTC_Minor = UINT32_MAX;
0023 
0024 static bool RTC_Is_present(void)
0025 {
0026   return RTC_Minor != UINT32_MAX;
0027 }
0028 
0029 /*
0030  *  rtc_initialize
0031  *
0032  *  Initialize the RTC driver
0033  */
0034 rtems_device_driver rtc_initialize(
0035   rtems_device_major_number  major,
0036   rtems_device_minor_number  minor_arg,
0037   void                      *arg
0038 )
0039 {
0040   rtems_device_minor_number minor;
0041   rtems_status_code status;
0042 
0043   for (minor=0; minor < RTC_Count ; minor++) {
0044     /*
0045      * First perform the configuration dependent probe, then the
0046      * device dependent probe
0047      */
0048 
0049     if (RTC_Table[minor].deviceProbe && RTC_Table[minor].deviceProbe(minor)) {
0050       /*
0051        * Use this device as the primary RTC
0052        */
0053       RTC_Minor = minor;
0054       break;
0055     }
0056   }
0057 
0058   if ( !RTC_Is_present() ) {
0059     /*
0060      * Failed to find an RTC -- this is not a fatal error.
0061      */
0062 
0063     return RTEMS_INVALID_NUMBER;
0064   }
0065 
0066   /*
0067    *  Register and initialize the primary RTC's
0068    */
0069   status = rtems_io_register_name( RTC_DEVICE_NAME, major, RTC_Minor );
0070   if (status != RTEMS_SUCCESSFUL) {
0071     rtems_fatal_error_occurred(status);
0072   }
0073 
0074   RTC_Table[minor].pDeviceFns->deviceInitialize( RTC_Minor );
0075 
0076   /*
0077    *  Now initialize any secondary RTC's
0078    */
0079   for ( minor++ ; minor<RTC_Count ; minor++) {
0080     /*
0081      * First perform the configuration dependent probe, then the
0082      * device dependent probe
0083      */
0084 
0085     if (RTC_Table[minor].deviceProbe && RTC_Table[minor].deviceProbe(minor)) {
0086       status = rtems_io_register_name(
0087         RTC_Table[minor].sDeviceName,
0088         major,
0089         minor );
0090       if (status != RTEMS_SUCCESSFUL) {
0091         rtems_fatal_error_occurred(status);
0092       }
0093 
0094       /*
0095        * Initialize the hardware device.
0096        */
0097       RTC_Table[minor].pDeviceFns->deviceInitialize(minor);
0098 
0099     }
0100   }
0101 
0102   setRealTimeToRTEMS();
0103   return RTEMS_SUCCESSFUL;
0104 }
0105 
0106 rtems_device_driver rtc_read(
0107   rtems_device_major_number  major,
0108   rtems_device_minor_number  minor,
0109   void *arg
0110 )
0111 {
0112   int rv = 0;
0113   rtems_libio_rw_args_t *rw = arg;
0114   rtems_time_of_day *tod = (rtems_time_of_day *) rw->buffer;
0115 
0116   rw->offset = 0;
0117   rw->bytes_moved = 0;
0118 
0119   if (!RTC_Is_present()) {
0120     return RTEMS_NOT_CONFIGURED;
0121   }
0122 
0123   if (rw->count != sizeof( rtems_time_of_day)) {
0124     return RTEMS_INVALID_SIZE;
0125   }
0126 
0127   rv = RTC_Table [RTC_Minor].pDeviceFns->deviceGetTime(
0128     RTC_Minor,
0129     tod
0130   );
0131   if (rv != 0) {
0132     return RTEMS_IO_ERROR;
0133   }
0134 
0135   rw->bytes_moved = rw->count;
0136 
0137   return RTEMS_SUCCESSFUL;
0138 }
0139 
0140 rtems_device_driver rtc_write(
0141   rtems_device_major_number  major,
0142   rtems_device_minor_number  minor,
0143   void *arg
0144 )
0145 {
0146   int rv = 0;
0147   rtems_libio_rw_args_t *rw = arg;
0148   const rtems_time_of_day *tod = (const rtems_time_of_day *) rw->buffer;
0149 
0150   rw->offset = 0;
0151   rw->bytes_moved = 0;
0152 
0153   if (!RTC_Is_present()) {
0154     return RTEMS_NOT_CONFIGURED;
0155   }
0156 
0157   if (rw->count != sizeof( rtems_time_of_day)) {
0158     return RTEMS_INVALID_SIZE;
0159   }
0160 
0161   rv = RTC_Table [RTC_Minor].pDeviceFns->deviceSetTime(
0162     RTC_Minor,
0163     tod
0164   );
0165   if (rv != 0) {
0166     return RTEMS_IO_ERROR;
0167   }
0168 
0169   rw->bytes_moved = rw->count;
0170 
0171   return RTEMS_SUCCESSFUL;
0172 }
0173 
0174 rtems_device_driver rtc_open(
0175   rtems_device_major_number major,
0176   rtems_device_minor_number minor,
0177   void *arg
0178 )
0179 {
0180   return RTEMS_SUCCESSFUL;
0181 }
0182 
0183 rtems_device_driver rtc_close(
0184   rtems_device_major_number major,
0185   rtems_device_minor_number minor,
0186   void *arg
0187 )
0188 {
0189   return RTEMS_SUCCESSFUL;
0190 }
0191 
0192 rtems_device_driver rtc_control(
0193   rtems_device_major_number major,
0194   rtems_device_minor_number minor,
0195   void *arg
0196 )
0197 {
0198   return RTEMS_NOT_IMPLEMENTED;
0199 }
0200 
0201 /*
0202  *  This routine copies the time from the real time clock to RTEMS
0203  */
0204 void setRealTimeToRTEMS()
0205 {
0206   rtems_time_of_day rtc_tod;
0207 
0208   if (!RTC_Is_present())
0209     return;
0210 
0211   RTC_Table[RTC_Minor].pDeviceFns->deviceGetTime(RTC_Minor, &rtc_tod);
0212   rtems_clock_set( &rtc_tod );
0213 }
0214 
0215 /*
0216  *  setRealTimeFromRTEMS
0217  *
0218  *  This routine copies the time from RTEMS to the real time clock
0219  */
0220 void setRealTimeFromRTEMS(void)
0221 {
0222   rtems_time_of_day rtems_tod;
0223 
0224   if (!RTC_Is_present())
0225     return;
0226 
0227   rtems_clock_get_tod( &rtems_tod );
0228   RTC_Table[RTC_Minor].pDeviceFns->deviceSetTime(RTC_Minor, &rtems_tod);
0229 }
0230 
0231 /*
0232  *  getRealTime
0233  *
0234  *  This routine reads the current time from the RTC.
0235  */
0236 void getRealTime(
0237   rtems_time_of_day *tod
0238 )
0239 {
0240   if (!RTC_Is_present())
0241     return;
0242 
0243   RTC_Table[RTC_Minor].pDeviceFns->deviceGetTime(RTC_Minor, tod);
0244 }
0245 
0246 /*
0247  *  setRealTime
0248  *
0249  *  This routine sets the RTC.
0250  */
0251 int setRealTime(
0252   const rtems_time_of_day *tod
0253 )
0254 {
0255   if (!RTC_Is_present())
0256     return -1;
0257 
0258   if (_TOD_Validate(tod, TOD_ENABLE_TICKS_VALIDATION) != RTEMS_SUCCESSFUL)
0259     return -1;
0260 
0261   RTC_Table[RTC_Minor].pDeviceFns->deviceSetTime(RTC_Minor, tod);
0262   return 0;
0263 }
0264 
0265 /*
0266  *  checkRealTime
0267  *
0268  *  This routine reads the returns the variance betweent the real time and
0269  *  RTEMS time.
0270  */
0271 int checkRealTime(void)
0272 {
0273   rtems_time_of_day rtems_tod;
0274   rtems_time_of_day rtc_tod;
0275   uint32_t   rtems_time;
0276   uint32_t   rtc_time;
0277 
0278   if (!RTC_Is_present())
0279     return -1;
0280 
0281   rtems_clock_get_tod( &rtems_tod );
0282   RTC_Table[RTC_Minor].pDeviceFns->deviceGetTime(RTC_Minor, &rtc_tod);
0283 
0284   rtems_time = _TOD_To_seconds( &rtems_tod );
0285   rtc_time = _TOD_To_seconds( &rtc_tod );
0286 
0287   return rtems_time - rtc_time;
0288 }