X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/1fe5f5eb5378a47bf0f3451762743c162e40faad..f044ca812256b421e793c4335ce1ffed74710a70:/lunaix-os/hal/rtc/mc146818a.c diff --git a/lunaix-os/hal/rtc/mc146818a.c b/lunaix-os/hal/rtc/mc146818a.c index 98ea807..e918ffd 100644 --- a/lunaix-os/hal/rtc/mc146818a.c +++ b/lunaix-os/hal/rtc/mc146818a.c @@ -11,6 +11,8 @@ */ #include +#include +#include #include @@ -39,6 +41,10 @@ #define RTC_REG_C 0xC #define RTC_REG_D 0xD +#define RTC_SET 0x80 +#define RTC_BIN (1 << 2) +#define RTC_HOURFORM24 (1 << 1) + #define RTC_BIN_ENCODED(reg) (reg & 0x04) #define RTC_24HRS_ENCODED(reg) (reg & 0x02) @@ -52,8 +58,7 @@ struct mc146818 { struct hwrtc* rtc_context; u32_t rtc_iv; - int ticking; - void (*on_tick_cb)(const struct hwrtc*); + u32_t tick_counts; }; #define rtc_state(data) ((struct mc146818*)(data)) @@ -72,28 +77,22 @@ rtc_write_reg(u8_t reg_selector, u8_t val) port_wrbyte(RTC_TARGET_PORT, val); } -static u8_t -bcd2dec(u8_t bcd) -{ - return ((bcd & 0xF0) >> 1) + ((bcd & 0xF0) >> 3) + (bcd & 0xf); -} - static void rtc_enable_timer() { - u8_t regB = rtc_read_reg(RTC_REG_B | WITH_NMI_DISABLED); - rtc_write_reg(RTC_REG_B | WITH_NMI_DISABLED, regB | RTC_TIMER_ON); + u8_t regB = rtc_read_reg(RTC_REG_B); + rtc_write_reg(RTC_REG_B, regB | RTC_TIMER_ON); } static void rtc_disable_timer() { - u8_t regB = rtc_read_reg(RTC_REG_B | WITH_NMI_DISABLED); - rtc_write_reg(RTC_REG_B | WITH_NMI_DISABLED, regB & ~RTC_TIMER_ON); + u8_t regB = rtc_read_reg(RTC_REG_B); + rtc_write_reg(RTC_REG_B, regB & ~RTC_TIMER_ON); } static void -clock_walltime(struct hwrtc* rtc, datetime_t* datetime) +rtc_getwalltime(struct hwrtc* rtc, datetime_t* datetime) { datetime_t current; @@ -111,24 +110,26 @@ clock_walltime(struct hwrtc* rtc, datetime_t* datetime) datetime->second = rtc_read_reg(RTC_REG_SEC); } while (!datatime_eq(datetime, ¤t)); - u8_t regbv = rtc_read_reg(RTC_REG_B); + datetime->year += RTC_CURRENT_CENTRY * 100; +} - // Convert from bcd to binary when needed - if (!RTC_BIN_ENCODED(regbv)) { - datetime->year = bcd2dec(datetime->year); - datetime->month = bcd2dec(datetime->month); - datetime->day = bcd2dec(datetime->day); - datetime->hour = bcd2dec(datetime->hour); - datetime->minute = bcd2dec(datetime->minute); - datetime->second = bcd2dec(datetime->second); - } +static void +rtc_setwalltime(struct hwrtc* rtc, datetime_t* datetime) +{ + u8_t reg = rtc_read_reg(RTC_REG_B); + reg = reg & ~RTC_SET; - // To 24 hour format - if (!RTC_24HRS_ENCODED(regbv) && (datetime->hour >> 7)) { - datetime->hour = 12 + (datetime->hour & 0x80); - } + rtc_write_reg(RTC_REG_B, reg | RTC_SET); - datetime->year += RTC_CURRENT_CENTRY * 100; + rtc_write_reg(RTC_REG_YRS, datetime->year - RTC_CURRENT_CENTRY * 100); + rtc_write_reg(RTC_REG_MTH, datetime->month); + rtc_write_reg(RTC_REG_DAY, datetime->day); + rtc_write_reg(RTC_REG_WDY, datetime->weekday); + rtc_write_reg(RTC_REG_HRS, datetime->hour); + rtc_write_reg(RTC_REG_MIN, datetime->minute); + rtc_write_reg(RTC_REG_SEC, datetime->second); + + rtc_write_reg(RTC_REG_B, reg & ~RTC_SET); } static int @@ -142,78 +143,81 @@ mc146818_check_support(struct hwrtc* rtc) } static void -rtc_init(struct hwrtc* rtc) +__rtc_tick(const isr_param* param) { - u8_t regA = rtc_read_reg(RTC_REG_A | WITH_NMI_DISABLED); - regA = (regA & ~0x7f) | RTC_FREQUENCY_1024HZ | RTC_DIVIDER_33KHZ; - rtc_write_reg(RTC_REG_A | WITH_NMI_DISABLED, regA); + struct mc146818* state = (struct mc146818*)isrm_get_payload(param); - rtc_state(rtc->data)->rtc_context = rtc; + state->tick_counts++; - // Make sure the rtc timer is disabled by default - rtc_disable_timer(); + (void)rtc_read_reg(RTC_REG_C); } -static struct mc146818 rtc_state = { .ticking = 0 }; - static void -__rtc_tick(const isr_param* param) +rtc_set_mask(struct hwrtc* rtc) { - rtc_state.on_tick_cb(rtc_state.rtc_context); - - (void)rtc_read_reg(RTC_REG_C); + rtc->state = RTC_STATE_MASKED; + rtc_disable_timer(); } static void -rtc_do_ticking(struct hwrtc* rtc, void (*on_tick)()) +rtc_cls_mask(struct hwrtc* rtc) { - if (!on_tick || rtc_state(rtc->data)->ticking) { - return; - } - struct mc146818* state = rtc_state(rtc->data); - state->ticking = 1; - state->on_tick_cb = on_tick; - - /* We realise that using rtc to tick something has an extremely rare use - * case (e.g., calibrating some timer). Therefore, we will release this - * allocated IV when rtc ticking is no longer required to save IV - * resources. - */ - state->rtc_iv = isrm_bindirq(PC_AT_IRQ_RTC, __rtc_tick); + rtc->state = 0; + state->tick_counts = 0; rtc_enable_timer(); } -static void -rtc_end_ticking(struct hwrtc* rtc) +static int +rtc_chfreq(struct hwrtc* rtc, int freq) +{ + return ENOTSUP; +} + +static int +rtc_getcnt(struct hwrtc* rtc) +{ + struct mc146818* state = rtc_state(rtc->data); + return state->tick_counts; +} + +static int +rtc_init(struct device_def* devdef) { - if (!rtc_state(rtc->data)->ticking) { - return; - } + u8_t reg = rtc_read_reg(RTC_REG_A); + reg = (reg & ~0x7f) | RTC_FREQUENCY_1024HZ | RTC_DIVIDER_33KHZ; + rtc_write_reg(RTC_REG_A, reg); + reg = RTC_BIN | RTC_HOURFORM24; + rtc_write_reg(RTC_REG_B, reg); + + // Make sure the rtc timer is disabled by default rtc_disable_timer(); - // do some delay, ensure there is no more interrupt from rtc before we - // release isr - port_delay(1000); + struct hwrtc* rtc = hwrtc_alloc_new("mc146818"); + struct mc146818* state = valloc(sizeof(struct mc146818)); - isrm_ivfree(rtc_state(rtc->data)->rtc_iv); + state->rtc_context = rtc; + state->rtc_iv = isrm_bindirq(PC_AT_IRQ_RTC, __rtc_tick); + isrm_set_payload(state->rtc_iv, (ptr_t)state); + + rtc->state = RTC_STATE_MASKED; + rtc->data = state; + rtc->base_freq = RTC_TIMER_BASE_FREQUENCY; + rtc->get_walltime = rtc_getwalltime; + rtc->set_walltime = rtc_setwalltime; + rtc->set_mask = rtc_set_mask; + rtc->cls_mask = rtc_cls_mask; + rtc->get_counts = rtc_getcnt; + rtc->chfreq = rtc_chfreq; - rtc_state(rtc->data)->ticking = 0; + return 0; } -static struct hwrtc hwrtc_mc146818a = { .name = "mc146818a", - .data = &rtc_state, - .init = rtc_init, - .base_freq = RTC_TIMER_BASE_FREQUENCY, - .supported = mc146818_check_support, - .get_walltime = clock_walltime, - .do_ticking = rtc_do_ticking, - .end_ticking = rtc_end_ticking }; - -struct hwrtc* -mc146818a_rtc_context() -{ - return &hwrtc_mc146818a; -} +static struct device_def devrtc_mc146818 = { + .name = "rtc_mc146818", + .class = DEVCLASS(DEVIF_SOC, DEVFN_TIME, DEV_RTC, 1), + .init = rtc_init +}; +EXPORT_DEVICE(mc146818, &devrtc_mc146818, load_earlystage); \ No newline at end of file