X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/2236410f4582ab45ae8c384dd6eeeef5d10aab15..refs/heads/nov/multiuser:/lunaix-os/hal/rtc/rtc_device.c diff --git a/lunaix-os/hal/rtc/rtc_device.c b/lunaix-os/hal/rtc/rtc_device.c index cd94a97..8676b3f 100644 --- a/lunaix-os/hal/rtc/rtc_device.c +++ b/lunaix-os/hal/rtc/rtc_device.c @@ -2,34 +2,51 @@ #include #include #include +#include #include -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) { - 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 -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: - rtc->set_mask(rtc); + ops->set_proactive(pot, false); 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*); - rtc->set_walltime(rtc, dt); + ops->set_walltime(pot, dt); 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 rtc->chfreq(rtc, *freq); + return ops->chfreq(pot, *freq); } - *freq = rtc->base_freq; + *freq = pot->base_freq; break; default: - return EINVAL; + return rtcdev->ops.exec_cmd(dev, req, args); } 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); } -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 -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) { - 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; - rtc->get_walltime(rtc, &dt); + pot->ops->get_walltime(pot, &dt); 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( - 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 -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() { - 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); }