static void mc13783_interrupt_thread(void) { uint32_t pending[2]; /* Enable mc13783 GPIO event */ gpio_enable_event(MC13783_EVENT_ID); while (1) { const struct mc13783_event *event, *event_last; wakeup_wait(&mc13783_svc_wake, TIMEOUT_BLOCK); if (mc13783_thread_id == 0) break; mc13783_read_regs(pmic_ints_regs, pending, 2); /* Only clear interrupts being dispatched */ pending[0] &= pmic_int_enabled[0]; pending[1] &= pmic_int_enabled[1]; mc13783_write_regs(pmic_ints_regs, pending, 2); /* Whatever is going to be serviced in this loop has been * acknowledged. Reenable interrupt and if anything was still * pending or became pending again, another signal will be * generated. */ imx31_regset32(&MC13783_GPIO_IMR, 1ul << MC13783_GPIO_LINE); event = mc13783_events; event_last = event + MC13783_NUM_EVENTS; /* .count is surely expected to be > 0 */ do { enum mc13783_event_sets set = event->set; uint32_t pnd = pending[set]; uint32_t mask = event->mask; if (pnd & mask) { event->callback(); pnd &= ~mask; pending[set] = pnd; } if ((pending[0] | pending[1]) == 0) break; /* Terminate early if nothing more to service */ } while (++event < event_last); } gpio_disable_event(MC13783_EVENT_ID); }
int rtc_read_datetime(struct tm *tm) { uint32_t regs[RTC_NUM_REGS]; int year, leap, month, day, hour, min; /* Read time, day, time - 2nd read of time should be the same or * greater */ do { if (mc13783_read_regs(rtc_registers, regs, RTC_NUM_REGS) < RTC_NUM_REGS) { /* Couldn't read registers */ return 0; } } /* If TOD counter turned over - reread */ while (regs[RTC_REG_TIME2] < regs[RTC_REG_TIME]); /* TOD: = 0 to 86399 */ hour = regs[RTC_REG_TIME] / 3600; regs[RTC_REG_TIME] -= hour*3600; tm->tm_hour = hour; min = regs[RTC_REG_TIME] / 60; regs[RTC_REG_TIME] -= min*60; tm->tm_min = min; tm->tm_sec = regs[RTC_REG_TIME]; /* DAY: 0 to 32767 */ day = regs[RTC_REG_DAY] + RTC_BASE_DAY_COUNT; /* Weekday */ tm->tm_wday = (day + 1) % 7; /* 1601/01/01 = Monday */ /* Get number of leaps for today */ leap = get_leap_count(day); year = (day - leap) / 365; /* Get number of leaps for yesterday */ leap = get_leap_count(day - 1); /* Get day number for year 0-364|365 */ day = day - leap - year * 365; year += 1601; /* Get the current month */ leap = is_leap_year(year); for (month = 0; month < 12; month++) { int days = month_table[leap][month]; if (day < days) break; day -= days; } tm->tm_mday = day + 1; /* 1 to 31 */ tm->tm_mon = month; /* 0 to 11 */ tm->tm_year = year % 100 + 100; return 7; }