DRIVER_API_RC qrk_cxxxx_rtc_set_alarm(struct qrk_cxxxx_rtc_alarm *alarm){ MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) &= ~QRK_RTC_INTERRUPT_ENABLE; if(false != alarm->alarm_enable) { if(alarm->callback_fn) { callback_fn = alarm->callback_fn; callback_param = alarm->callback_param; } MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_EOI); MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CMR) = alarm->alarm_rtc_val; SET_INTERRUPT_HANDLER(SOC_RTC_INTERRUPT, rtc_isr); /* unmask RTC interrupts to qrk */ MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_INT_RTC_MASK_OFFSET) = QRK_INT_RTC_UNMASK_QRK; MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) |= QRK_RTC_INTERRUPT_ENABLE; MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) &= ~QRK_RTC_INTERRUPT_MASK; } else { MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_INT_RTC_MASK_OFFSET) = ~(0); } pm_wakelock_release(&rtc_wakelock); pm_wakelock_acquire(&rtc_wakelock, RTC_WAKELOCK_TIMEOUT); return DRV_RC_OK; }
/*! \fn int qrk_cxxxx_rtc_set_alarm(struct device *rtc_dev, const uint32_t alarm_val) * * \brief Function to set an RTC alarm * * \param alarm_val Alarm value * * \return DEV_OK on success * DEV_USED otherwise */ int qrk_cxxxx_rtc_set_alarm(struct device *rtc_dev, const uint32_t alarm_val) { OS_ERR_TYPE err; MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) &= ~QRK_RTC_INTERRUPT_ENABLE; MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_EOI); MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CMR) = alarm_val; irq_enable(SOC_RTC_INTERRUPT); /* unmask RTC interrupts to quark */ MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_INT_RTC_MASK_OFFSET) = QRK_INT_RTC_UNMASK_QRK; MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) |= QRK_RTC_INTERRUPT_ENABLE; MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) &= ~QRK_RTC_INTERRUPT_MASK; pm_wakelock_acquire(&rtc_wakelock); timer_start(rtc_wakelock_timer, RTC_WAKELOCK_DELAY, &err); if (err != E_OS_OK) { pm_wakelock_release(&rtc_wakelock); return DEV_USED; } return DEV_OK; }
/*! \fn DRIVER_API_RC qrk_cxxxx_rtc_set_config(struct qrk_cxxxx_rtc_config *config) * * \brief Function to configure the RTC * * \param config : pointer to a RTC configuration structure * * \return DRV_RC_OK on success\n * DRV_RC_FAIL otherwise */ DRIVER_API_RC qrk_cxxxx_rtc_set_config(struct qrk_cxxxx_rtc_config *config) { OS_ERR_TYPE err; /* Set RTC divider - 32.768khz / 32768 = 1 second. * Note: Divider not implemented in standard emulation image. */ qrk_cxxxx_rtc_clock_frequency(SCSS_RTC_CLK_DIV_1_HZ); MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) |= QRK_RTC_INTERRUPT_MASK; /* set initial RTC value */ while (config->initial_rtc_val != MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCVR)) { MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CLR) = config->initial_rtc_val; } pm_wakelock_acquire(&rtc_wakelock); timer_start(rtc_wakelock_timer, RTC_WAKELOCK_DELAY, &err); if(err != E_OS_OK) { pm_wakelock_release(&rtc_wakelock); return DRV_RC_BUSY; } MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) &= ~QRK_RTC_INTERRUPT_MASK; return DRV_RC_OK; }
/*! \fn int qrk_cxxxx_rtc_set_config(struct device *dev, struct rtc_config *config) * * \brief Function to configure the RTC * * \param config : pointer to a RTC configuration structure * * \return DEV_OK on success\n * DEV_USED otherwise */ static int qrk_cxxxx_rtc_set_config(struct device * rtc_dev, struct rtc_config * config) { OS_ERR_TYPE err; /* Set RTC divider - 32.768khz / 32768 = 1 second. * Note: Divider not implemented in standard emulation image. */ if (!is_rtc_init_done) { qrk_cxxxx_rtc_one_time_setup(rtc_dev); is_rtc_init_done = true; } /* Set RTC divider 1HZ */ qrk_cxxxx_rtc_clock_frequency(SCSS_RTC_CLK_DIV_1_HZ); MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) |= QRK_RTC_INTERRUPT_MASK; if (false != config->alarm_enable) { if (config->cb_fn) callback_fn = config->cb_fn; } else { /* set initial RTC value */ while (config->init_val != MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCVR)) { MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CLR) = config->init_val; } MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_INT_RTC_MASK_OFFSET) = ~(0); } pm_wakelock_acquire(&rtc_wakelock); timer_start(rtc_wakelock_timer, RTC_WAKELOCK_DELAY, &err); if (err != E_OS_OK) { pm_wakelock_release(&rtc_wakelock); return DEV_USED; } MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCR) &= ~QRK_RTC_INTERRUPT_MASK; return DEV_OK; }
static void qrk_cxxxx_rtc_wakelock_timer_callback(void* data) { pm_wakelock_release(&rtc_wakelock); }