Пример #1
0
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);
}
Пример #2
0
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;
}