allow specifiying access mode when creating twifs file node
[lunaix-os.git] / lunaix-os / hal / rtc / rtc_device.c
index cd94a97e7aeacc3db7cde9c53a1cfa46e7f2ee7f..8676b3fce733ad52fed8c5674fd5af313b093a79 100644 (file)
@@ -2,34 +2,51 @@
 #include <lunaix/fs/twimap.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/status.h>
 #include <lunaix/fs/twimap.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/status.h>
+#include <lunaix/syslog.h>
 
 #include <hal/hwrtc.h>
 
 
 #include <hal/hwrtc.h>
 
-const struct hwrtc* sysrtc;
-static int rtc_count = 0;
+const struct hwrtc_potens* sysrtc = NULL;
 
 
-DEFINE_LLIST(rtcs);
+static DEFINE_LLIST(rtcs);
+
+LOG_MODULE("hwrtc")
 
 void
 hwrtc_walltime(datetime_t* dt)
 {
 
 void
 hwrtc_walltime(datetime_t* dt)
 {
-    sysrtc->get_walltime(sysrtc, dt);
+    sysrtc->ops->get_walltime(sysrtc, dt);
+}
+
+static inline struct hwrtc_potens*
+__rtc_potens(struct device* wrapper)
+{
+    struct potens_meta* pot;
+    pot = device_get_potens(wrapper, potens(HWRTC));
+    return ({ assert(pot); get_potens(pot, struct hwrtc_potens); });
 }
 
 static int
 }
 
 static int
-hwrtc_ioctl(struct device* dev, u32_t req, va_list args)
+__hwrtc_ioctl(struct device* dev, u32_t req, va_list args)
 {
 {
-    struct hwrtc* rtc = (struct hwrtc*)dev->underlay;
+    struct hwrtc_potens* pot;
+    struct hwrtc_potens_ops* ops;
+    struct device* rtcdev;
+
+    rtcdev = (struct device*) dev->underlay;
+    pot = __rtc_potens(rtcdev);
+    ops = pot->ops;
+
     switch (req) {
         case RTCIO_IMSK:
     switch (req) {
         case RTCIO_IMSK:
-            rtc->set_mask(rtc);
+            ops->set_proactive(pot, false);
             break;
         case RTCIO_IUNMSK:
             break;
         case RTCIO_IUNMSK:
-            rtc->cls_mask(rtc);
+            ops->set_proactive(pot, true);
             break;
         case RTCIO_SETDT:
             datetime_t* dt = va_arg(args, datetime_t*);
             break;
         case RTCIO_SETDT:
             datetime_t* dt = va_arg(args, datetime_t*);
-            rtc->set_walltime(rtc, dt);
+            ops->set_walltime(pot, dt);
             break;
         case RTCIO_SETFREQ:
             ticks_t* freq = va_arg(args, ticks_t*);
             break;
         case RTCIO_SETFREQ:
             ticks_t* freq = va_arg(args, ticks_t*);
@@ -38,95 +55,128 @@ hwrtc_ioctl(struct device* dev, u32_t req, va_list args)
                 return EINVAL;
             }
             if (*freq) {
                 return EINVAL;
             }
             if (*freq) {
-                return rtc->chfreq(rtc, *freq);
+                return ops->chfreq(pot, *freq);
             }
 
             }
 
-            *freq = rtc->base_freq;
+            *freq = pot->base_freq;
 
             break;
         default:
 
             break;
         default:
-            return EINVAL;
+            return rtcdev->ops.exec_cmd(dev, req, args);
     }
 
     return 0;
 }
 
 static int
     }
 
     return 0;
 }
 
 static int
-hwrtc_read(struct device* dev, void* buf, size_t offset, size_t len)
+__hwrtc_read(struct device* dev, void* buf, size_t offset, size_t len)
 {
 {
-    struct hwrtc* rtc = (struct hwrtc*)dev->underlay;
-    *((ticks_t*)buf) = rtc->get_counts(rtc);
+    struct hwrtc_potens* pot;
+
+    pot = __rtc_potens((struct device*)dev->underlay);
+    *((ticks_t*)buf) = pot->live;
 
     return sizeof(ticks_t);
 }
 
 
     return sizeof(ticks_t);
 }
 
-struct hwrtc*
-hwrtc_alloc_new(char* name)
+static struct devclass proxy_rtc_clas = DEVCLASS(LUNAIX, TIME, RTC);
+
+static void
+__hwrtc_create_proxy(struct hwrtc_potens* pot, struct device* raw_rtcdev)
 {
 {
-    struct hwrtc* rtc_instance = valloc(sizeof(struct hwrtc));
+    struct device* dev;
 
 
-    if (!rtc_instance) {
-        return NULL;
-    }
+    dev = device_allocsys(NULL, raw_rtcdev);
 
 
-    llist_append(&rtcs, &rtc_instance->rtc_list);
+    dev->ops.exec_cmd = __hwrtc_ioctl;
+    dev->ops.read = __hwrtc_read;
 
 
-    rtc_instance->id = rtc_count++;
-    rtc_instance->name = name;
-    struct device* rtcdev = device_allocsys(NULL, rtc_instance);
+    register_device_var(dev, &proxy_rtc_clas, "rtc");
 
 
-    rtcdev->ops.exec_cmd = hwrtc_ioctl;
-    rtcdev->ops.read = hwrtc_read;
+    pot->rtc_proxy = dev;
+}
 
 
-    rtc_instance->rtc_dev = rtcdev;
+struct hwrtc_potens*
+hwrtc_attach_potens(struct device* raw_rtcdev, struct hwrtc_potens_ops* ops)
+{
+    struct hwrtc_potens* hwpot;
 
 
-    return rtc_instance;
+    if (!potens_check_unique(raw_rtcdev, potens(HWRTC)))
+    {
+        return NULL;
+    }
+
+    hwpot = new_potens(potens(HWRTC), struct hwrtc_potens);
+    hwpot->ops = ops;
+    
+    device_grant_potens(raw_rtcdev, potens_meta(hwpot));
+    llist_append(&rtcs, &hwpot->rtc_potentes);
+
+    __hwrtc_create_proxy(hwpot, raw_rtcdev);
+
+    return hwpot;
 }
 
 void
 }
 
 void
-hwrtc_register(struct devclass* class, struct hwrtc* rtc)
+hwrtc_init()
 {
 {
-    if (unlikely(!sysrtc)) {
-        sysrtc = rtc;
+    assert(!llist_empty(&rtcs));
+
+    sysrtc = list_entry(rtcs.next, struct hwrtc_potens, rtc_potentes);
+    
+    if (!sysrtc->ops->calibrate) {
+        return;
     }
 
     }
 
-    class->variant = rtc->id;
-    device_register(rtc->rtc_dev, class, "rtc%d", rtc->id);
+    int err = sysrtc->ops->calibrate(sysrtc);
+    if (err) {
+        FATAL("failed to calibrate rtc. name='%s', err=%d", 
+                potens_dev(sysrtc)->name_val, err);
+    }
 }
 
 static void
 __hwrtc_readinfo(struct twimap* mapping)
 {
 }
 
 static void
 __hwrtc_readinfo(struct twimap* mapping)
 {
-    struct hwrtc* rtc = twimap_data(mapping, struct hwrtc*);
-    twimap_printf(mapping, "name: %s\n", rtc->name);
-    twimap_printf(mapping, "frequency: %dHz\n", rtc->base_freq);
-    twimap_printf(mapping, "ticks count: %d\n", rtc->get_counts(rtc));
-    twimap_printf(
-      mapping, "ticking: %s\n", (rtc->state & RTC_STATE_MASKED) ? "no" : "yes");
+    struct hwrtc_potens* pot;
+    struct device* owner;
+
+    pot = twimap_data(mapping, struct hwrtc_potens*);
+    owner = pot->pot_meta.owner;
+
+    twimap_printf(mapping, "device: %x.%x\n", 
+                    owner->ident.fn_grp, owner->ident.unique);
+
+    twimap_printf(mapping, "frequency: %dHz\n", pot->base_freq);
+    twimap_printf(mapping, "ticks count: %d\n", pot->live);
+    twimap_printf(mapping, "ticking: %s\n",
+                  (pot->state & RTC_STATE_MASKED) ? "no" : "yes");
 
     datetime_t dt;
 
     datetime_t dt;
-    rtc->get_walltime(rtc, &dt);
+    pot->ops->get_walltime(pot, &dt);
 
     twimap_printf(
 
     twimap_printf(
-      mapping, "recorded date: %d/%d/%d\n", dt.year, dt.month, dt.day);
+        mapping, "recorded date: %d/%d/%d\n", dt.year, dt.month, dt.day);
     twimap_printf(
     twimap_printf(
-      mapping, "recorded time: %d:%d:%d\n", dt.hour, dt.minute, dt.second);
+        mapping, "recorded time: %d:%d:%d\n", dt.hour, dt.minute, dt.second);
     twimap_printf(mapping, "recorded weekday: %d\n", dt.weekday);
 }
 
 static void
     twimap_printf(mapping, "recorded weekday: %d\n", dt.weekday);
 }
 
 static void
-hwrtc_twifs_export(struct hwrtc* rtc)
+hwrtc_twifs_export(struct hwrtc_potens* pot)
 {
 {
-    const char* name = rtc->rtc_dev->name.value;
-    struct twimap* rtc_mapping = twifs_mapping(NULL, rtc, name);
+    const char* name = pot->rtc_proxy->name_val;
+    struct twimap* rtc_mapping;
+    
+    rtc_mapping = twifs_mapping(NULL, pot, FSACL_aR, name);
     rtc_mapping->read = __hwrtc_readinfo;
 }
 
 static void
 hwrtc_twifs_export_all()
 {
     rtc_mapping->read = __hwrtc_readinfo;
 }
 
 static void
 hwrtc_twifs_export_all()
 {
-    struct hwrtc *pos, *next;
-    llist_for_each(pos, next, &rtcs, rtc_list)
+    struct hwrtc_potens *pos, *next;
+    llist_for_each(pos, next, &rtcs, rtc_potentes)
     {
         hwrtc_twifs_export(pos);
     }
     {
         hwrtc_twifs_export(pos);
     }