rewrite the device subsystem interfaces (#48)
[lunaix-os.git] / lunaix-os / hal / timer / timer_device.c
index 1db814764346acc7b03e56de810773a3f2cc8350..085f6bd95c36aebd787fbb8f877a28b849b52636 100644 (file)
@@ -3,26 +3,23 @@
 
 #include <hal/hwtimer.h>
 
-const struct hwtimer* systimer;
+const struct hwtimer_pot* systimer = NULL;
 
-ticks_t
-hwtimer_base_frequency()
-{
-    assert(systimer);
-    return systimer->base_freq;
-}
+static struct device_alias* timer_alias;
+static DEFINE_LLIST(timer_devices);
 
 ticks_t
 hwtimer_current_systicks()
 {
     assert(systimer);
-    return systimer->systicks();
+    return systimer->systick_raw;
 }
 
 ticks_t
 hwtimer_to_ticks(u32_t value, int unit)
 {
     assert(systimer);
+
     // in case system frequency is less than 1000Hz
     if (unit != TIME_MS) {
         return systimer->running_freq * unit * value;
@@ -33,34 +30,66 @@ hwtimer_to_ticks(u32_t value, int unit)
     return freq_ms * value;
 }
 
-static int
-__hwtimer_ioctl(struct device* dev, u32_t req, va_list args)
+static struct hwtimer_pot*
+__select_timer()
 {
-    struct hwtimer* hwt = (struct hwtimer*)dev->underlay;
-    switch (req) {
-        case TIMERIO_GETINFO:
-            // TODO
-            break;
-
-        default:
-            break;
+    struct hwtimer_pot *pos, *n, *sel = NULL;
+
+    llist_for_each(pos, n, &timer_devices, timers)
+    {
+        if (unlikely(!sel)) {
+            sel = pos;
+            continue;
+        }
+
+        if (sel->precedence < pos->precedence) {
+            sel = pos;
+        }
     }
-    return 0;
+
+    return sel;
 }
 
 void
 hwtimer_init(u32_t hertz, void* tick_callback)
 {
-    struct hwtimer* hwt_ctx = select_platform_timer();
+    struct hwtimer_pot* selected;
+    struct device* time_dev;
+
+    selected = __select_timer();
 
-    hwt_ctx->init(hwt_ctx, hertz, tick_callback);
-    hwt_ctx->running_freq = hertz;
+    assert(selected);
+    systimer = selected;
 
-    systimer = hwt_ctx;
+    selected->callback = tick_callback;
+    selected->running_freq = hertz;
+
+    selected->ops->calibrate(selected, hertz);
+
+    time_dev = potens_dev(selected);
+    timer_alias = device_addalias(NULL, dev_meta(time_dev), "timer");
+}
+
+
+struct hwtimer_pot*
+hwtimer_attach_potens(struct device* dev, int precedence, 
+                      struct hwtimer_pot_ops* ops)
+{
+    struct hwtimer_pot* hwpot;
+    struct potens_meta* pot;
+
+    if (!potens_check_unique(dev, potens(HWTIMER)))
+    {
+        return NULL;
+    }
 
-    struct device* timerdev = device_allocsys(NULL, hwt_ctx);
+    hwpot = new_potens(potens(HWTIMER), struct hwtimer_pot);
+    hwpot->ops = ops;
+    hwpot->precedence = precedence;
+    
+    device_grant_potens(dev, potens_meta(hwpot));
 
-    timerdev->ops.exec_cmd = __hwtimer_ioctl;
+    llist_append(&timer_devices, &hwpot->timers);
 
-    register_device(timerdev, &hwt_ctx->class, hwt_ctx->name);
+    return hwpot;
 }
\ No newline at end of file