Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSBSPsARMLPC32XX
0007  *
0008  * @brief RTC configuration.
0009  */
0010 
0011 /*
0012  * Copyright (C) 2009, 2011 embedded brains GmbH & Co. KG
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #include <libchip/rtc.h>
0037 
0038 #include <bsp.h>
0039 #include <bsp/lpc32xx.h>
0040 #include <rtems/rtems/clockimpl.h>
0041 
0042 #include <time.h>
0043 
0044 #define LPC32XX_RTC_COUNT 1U
0045 
0046 #define LPC32XX_RTC_COUNTER_DELTA 0xfffffffeU
0047 
0048 #define LPC32XX_RTC_KEY 0xb5c13f27U
0049 
0050 #define LPC32XX_RTC_CTRL_FORCE_ONSW (1U << 7)
0051 #define LPC32XX_RTC_CTRL_STOP (1U << 6)
0052 #define LPC32XX_RTC_CTRL_RESET (1U << 4)
0053 #define LPC32XX_RTC_CTRL_MATCH_1_ONSW (1U << 3)
0054 #define LPC32XX_RTC_CTRL_MATCH_0_ONSW (1U << 2)
0055 #define LPC32XX_RTC_CTRL_MATCH_1_INTR (1U << 1)
0056 #define LPC32XX_RTC_CTRL_MATCH_0_INTR (1U << 0)
0057 
0058 static void lpc32xx_rtc_set(uint32_t val)
0059 {
0060   unsigned i = lpc32xx_arm_clk() / LPC32XX_OSCILLATOR_RTC;
0061 
0062   lpc32xx.rtc.ctrl |= LPC32XX_RTC_CTRL_STOP;
0063   lpc32xx.rtc.ucount = val;
0064   lpc32xx.rtc.dcount = LPC32XX_RTC_COUNTER_DELTA - val;
0065   lpc32xx.rtc.ctrl &= ~LPC32XX_RTC_CTRL_STOP;
0066 
0067   /* It needs some time before we can read the values back */
0068   while (i != 0) {
0069     __asm__ volatile ("nop");
0070     --i;
0071   }
0072 }
0073 
0074 static void lpc32xx_rtc_reset(void)
0075 {
0076   lpc32xx.rtc.ctrl = LPC32XX_RTC_CTRL_RESET;
0077   lpc32xx.rtc.ctrl = 0;
0078   lpc32xx.rtc.key = LPC32XX_RTC_KEY;
0079   lpc32xx_rtc_set(0);
0080 }
0081 
0082 static void lpc32xx_rtc_initialize(int minor)
0083 {
0084   uint32_t up_first = 0;
0085   uint32_t up_second = 0;
0086   uint32_t down_first = 0;
0087   uint32_t down_second = 0;
0088 
0089   if (lpc32xx.rtc.key != LPC32XX_RTC_KEY) {
0090     lpc32xx_rtc_reset();
0091   }
0092 
0093   do {
0094     up_first = lpc32xx.rtc.ucount;
0095     down_first = lpc32xx.rtc.dcount;
0096     up_second = lpc32xx.rtc.ucount;
0097     down_second = lpc32xx.rtc.dcount;
0098   } while (up_first != up_second || down_first != down_second);
0099 
0100   if (up_first + down_first != LPC32XX_RTC_COUNTER_DELTA) {
0101     lpc32xx_rtc_reset();
0102   }
0103 }
0104 
0105 static int lpc32xx_rtc_get_time(int minor, rtems_time_of_day *tod)
0106 {
0107   struct timeval now = {
0108     .tv_sec = lpc32xx.rtc.ucount,
0109     .tv_usec = 0
0110   };
0111   struct tm time;
0112 
0113   gmtime_r(&now.tv_sec, &time);
0114 
0115   tod->year   = time.tm_year + 1900;
0116   tod->month  = time.tm_mon + 1;
0117   tod->day    = time.tm_mday;
0118   tod->hour   = time.tm_hour;
0119   tod->minute = time.tm_min;
0120   tod->second = time.tm_sec;
0121   tod->ticks  = 0;
0122 
0123   return RTEMS_SUCCESSFUL;
0124 }
0125 
0126 static int lpc32xx_rtc_set_time(int minor, const rtems_time_of_day *tod)
0127 {
0128   lpc32xx_rtc_set(_TOD_To_seconds(tod));
0129 
0130   return 0;
0131 }
0132 
0133 static bool lpc32xx_rtc_probe(int minor)
0134 {
0135   return true;
0136 }
0137 
0138 const rtc_fns lpc32xx_rtc_ops = {
0139   .deviceInitialize = lpc32xx_rtc_initialize,
0140   .deviceGetTime = lpc32xx_rtc_get_time,
0141   .deviceSetTime = lpc32xx_rtc_set_time
0142 };
0143 
0144 size_t RTC_Count = LPC32XX_RTC_COUNT;
0145 
0146 rtc_tbl RTC_Table [LPC32XX_RTC_COUNT] = {
0147   {
0148     .sDeviceName = "/dev/rtc",
0149     .deviceType = RTC_CUSTOM,
0150     .pDeviceFns = &lpc32xx_rtc_ops,
0151     .deviceProbe = lpc32xx_rtc_probe,
0152     .pDeviceParams = NULL,
0153     .ulCtrlPort1 = 0,
0154     .ulDataPort = 0,
0155     .getRegister = NULL,
0156     .setRegister = NULL
0157   }
0158 };