1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2021-11-4 GuEe-GUI first version
9 */
10
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include <sys/time.h>
14 #include <board.h>
15
16 #include "drv_rtc.h"
17
18 #ifdef BSP_USING_RTC
19
20 #define RTC_DR 0x00 /* data read register */
21 #define RTC_MR 0x04 /* match register */
22 #define RTC_LR 0x08 /* data load register */
23 #define RTC_CR 0x0c /* control register */
24 #define RTC_IMSC 0x10 /* interrupt mask and set register */
25 #define RTC_RIS 0x14 /* raw interrupt status register */
26 #define RTC_MIS 0x18 /* masked interrupt status register */
27 #define RTC_ICR 0x1c /* interrupt clear register */
28
29 #define RTC_CR_OPEN 1
30 #define RTC_CR_CLOSE 0
31
32 static struct hw_rtc_device rtc_device;
33 static rt_ubase_t pl031_rtc_base = PL031_RTC_BASE;
34
pl031_read32(rt_ubase_t offset)35 rt_inline rt_uint32_t pl031_read32(rt_ubase_t offset)
36 {
37 return (*((volatile unsigned int *)(pl031_rtc_base + offset)));
38 }
39
pl031_write32(rt_ubase_t offset,rt_uint32_t value)40 rt_inline void pl031_write32(rt_ubase_t offset, rt_uint32_t value)
41 {
42 (*((volatile unsigned int *)(pl031_rtc_base + offset))) = value;
43 }
44
pl031_rtc_init(rt_device_t dev)45 static rt_err_t pl031_rtc_init(rt_device_t dev)
46 {
47 return RT_EOK;
48 }
49
pl031_rtc_open(rt_device_t dev,rt_uint16_t oflag)50 static rt_err_t pl031_rtc_open(rt_device_t dev, rt_uint16_t oflag)
51 {
52 pl031_write32(RTC_CR, RTC_CR_OPEN);
53 return RT_EOK;
54 }
55
pl031_rtc_close(rt_device_t dev)56 static rt_err_t pl031_rtc_close(rt_device_t dev)
57 {
58 pl031_write32(RTC_CR, RTC_CR_CLOSE);
59 return RT_EOK;
60 }
61
pl031_rtc_control(rt_device_t dev,int cmd,void * args)62 static rt_err_t pl031_rtc_control(rt_device_t dev, int cmd, void *args)
63 {
64
65 RT_ASSERT(dev != RT_NULL);
66
67 switch (cmd)
68 {
69 case RT_DEVICE_CTRL_RTC_GET_TIME:
70 *(rt_uint32_t *)args = pl031_read32(RTC_DR);
71 break;
72 case RT_DEVICE_CTRL_RTC_SET_TIME:
73 pl031_write32(RTC_LR, *(time_t *)args);
74 break;
75 default:
76 return -RT_EINVAL;
77 }
78 return RT_EOK;
79 }
80
pl031_rtc_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)81 static rt_ssize_t pl031_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
82 {
83 pl031_rtc_control(dev, RT_DEVICE_CTRL_RTC_GET_TIME, buffer);
84 return size;
85 }
86
pl031_rtc_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)87 static rt_ssize_t pl031_rtc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
88 {
89 pl031_rtc_control(dev, RT_DEVICE_CTRL_RTC_SET_TIME, (void *)buffer);
90 return size;
91 }
92
93 const static struct rt_device_ops pl031_rtc_ops =
94 {
95 .init = pl031_rtc_init,
96 .open = pl031_rtc_open,
97 .close = pl031_rtc_close,
98 .read = pl031_rtc_read,
99 .write = pl031_rtc_write,
100 .control = pl031_rtc_control
101 };
102
rt_hw_rtc_init(void)103 int rt_hw_rtc_init(void)
104 {
105 pl031_rtc_base = (rt_size_t)rt_ioremap((void *)pl031_rtc_base, PL031_RTC_SIZE);
106
107 rt_memset(&rtc_device, 0, sizeof(rtc_device));
108
109 rtc_device.device.type = RT_Device_Class_RTC;
110 rtc_device.device.rx_indicate = RT_NULL;
111 rtc_device.device.tx_complete = RT_NULL;
112 rtc_device.device.ops = &pl031_rtc_ops;
113 rtc_device.device.user_data = RT_NULL;
114
115 /* register a rtc device */
116 rt_device_register(&rtc_device.device, "rtc0", RT_DEVICE_FLAG_RDWR);
117 rt_soft_rtc_set_source("rtc0");
118 return 0;
119 }
120 INIT_DEVICE_EXPORT(rt_hw_rtc_init);
121 #endif /* BSP_USING_RTC */
122