feat: better rtc framework which aims to remove single rtc restrictions.
[lunaix-os.git] / lunaix-os / hal / rtc / hwrtc.c
1 #include <hal/hwrtc.h>
2
3 #include <lunaix/fs/twifs.h>
4 #include <lunaix/fs/twimap.h>
5 #include <lunaix/mm/valloc.h>
6 #include <lunaix/status.h>
7
8 #include <usr/lunaix/ioctl_defs.h>
9
10 const struct hwrtc* primary_rtc;
11 static int rtc_count = 0;
12
13 DEFINE_LLIST(rtcs);
14
15 void
16 hwrtc_init()
17 {
18     ptr_t init;
19     int index;
20     ldga_foreach(rtcdev, ptr_t, index, init)
21     {
22         ((void (*)())init)();
23     }
24 }
25
26 void
27 hwrtc_walltime(datetime_t* dt)
28 {
29     primary_rtc->get_walltime(primary_rtc, dt);
30 }
31
32 static int
33 hwrtc_ioctl(struct device* dev, u32_t req, va_list args)
34 {
35     struct hwrtc* rtc = (struct hwrtc*)dev->underlay;
36     switch (req) {
37         case RTCIO_IMSK:
38             rtc->set_mask(rtc);
39             break;
40         case RTCIO_IUNMSK:
41             rtc->cls_mask(rtc);
42             break;
43         case RTCIO_SETDT:
44             datetime_t* dt = va_arg(args, datetime_t*);
45             rtc->set_walltime(rtc, dt);
46             break;
47         case RTCIO_SETFREQ:
48             ticks_t* freq = va_arg(args, ticks_t*);
49
50             if (!freq) {
51                 return EINVAL;
52             }
53             if (*freq) {
54                 return rtc->chfreq(rtc, *freq);
55             }
56
57             *freq = rtc->base_freq;
58
59             break;
60         default:
61             return EINVAL;
62     }
63
64     return 0;
65 }
66
67 static int
68 hwrtc_read(struct device* dev, void* buf, size_t offset, size_t len)
69 {
70     struct hwrtc* rtc = (struct hwrtc*)dev->underlay;
71     *((ticks_t*)buf) = rtc->get_counts(rtc);
72
73     return sizeof(ticks_t);
74 }
75
76 struct hwrtc*
77 hwrtc_alloc_new(char* name)
78 {
79     struct hwrtc* rtc_instance = valloc(sizeof(struct hwrtc));
80
81     if (!rtc_instance) {
82         return NULL;
83     }
84
85     llist_append(&rtcs, &rtc_instance->rtc_list);
86
87     if (!primary_rtc) {
88         primary_rtc = rtc_instance;
89     }
90
91     rtc_instance->name = name;
92     struct device* rtcdev =
93       device_addsys(NULL, rtc_instance, "rtc%d", rtc_count);
94
95     rtcdev->ops.exec_cmd = hwrtc_ioctl;
96     rtcdev->ops.read = hwrtc_read;
97
98     rtc_instance->rtc_dev = rtcdev;
99
100     rtc_count++;
101
102     return rtc_instance;
103 }
104
105 static void
106 __hwrtc_readinfo(struct twimap* mapping)
107 {
108     struct hwrtc* rtc = twimap_data(mapping, struct hwrtc*);
109     twimap_printf(mapping, "device: %s\n", rtc->name);
110     twimap_printf(mapping, "frequency: %dHz\n", rtc->base_freq);
111     twimap_printf(mapping, "ticks count: %d\n", rtc->get_counts(rtc));
112     twimap_printf(
113       mapping, "ticking: %s\n", (rtc->state & RTC_STATE_MASKED) ? "no" : "yes");
114
115     datetime_t dt;
116     rtc->get_walltime(rtc, &dt);
117
118     twimap_printf(
119       mapping, "recorded date: %d/%d/%d\n", dt.year, dt.month, dt.day);
120     twimap_printf(
121       mapping, "recorded time: %d:%d:%d\n", dt.hour, dt.minute, dt.second);
122     twimap_printf(mapping, "recorded weekday: %d\n", dt.weekday);
123 }
124
125 static void
126 hwrtc_twifs_export(struct hwrtc* rtc)
127 {
128     const char* name = rtc->rtc_dev->name.value;
129     struct twimap* rtc_mapping = twifs_mapping(NULL, rtc, name);
130     rtc_mapping->read = __hwrtc_readinfo;
131 }
132
133 static void
134 hwrtc_twifs_export_all()
135 {
136     struct hwrtc *pos, *next;
137     llist_for_each(pos, next, &rtcs, rtc_list)
138     {
139         hwrtc_twifs_export(pos);
140     }
141 }
142 EXPORT_TWIFS_PLUGIN(rtc_fsexport, hwrtc_twifs_export_all);