File indexing completed on 2025-05-11 08:23:04
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
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
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 };