static int qrk_cxxxx_rtc_init(struct device* dev) { const uint32_t expected_freq = SCSS_RTC_CLK_DIV_1_HZ | SCSS_CCU_RTC_CLK_DIV_EN; qrk_cxxxx_rtc_enable(dev); uint32_t curr_freq = MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_CCU_SYS_CLK_CTL_OFFSET) & (SCSS_CCU_RTC_CLK_DIV_EN | SCSS_RTC_CLK_DIV_MASK); pm_wakelock_init(&rtc_wakelock, RTC_WAKELOCK); // disable interrupt 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); /* Reset initial value only if RTC wasn't enabled at right frequency at * beginning of init */ if (expected_freq != curr_freq) { // Set RTC divider 4096HZ for fast uptade qrk_cxxxx_rtc_clock_frequency(SCSS_RTC_CLK_DIV_4096_HZ); /* set intial RTC value 0 */ MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CLR) = 0; while (0 != MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCVR)) { MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CLR) = 0; } } // Set RTC divider 1HZ qrk_cxxxx_rtc_clock_frequency(SCSS_RTC_CLK_DIV_1_HZ); return 0; }
/*! \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; }
static int qrk_cxxxx_rtc_init(struct device* dev) { OS_ERR_TYPE err; const uint32_t expected_freq = SCSS_RTC_CLK_DIV_1_HZ | SCSS_CCU_RTC_CLK_DIV_EN; qrk_cxxxx_rtc_enable(dev); rtc_wakelock_timer = timer_create(qrk_cxxxx_rtc_wakelock_timer_callback, NULL, RTC_WAKELOCK_DELAY, false, false, &err); if (E_OS_OK != err) pr_error(LOG_MODULE_DRV,"rtc_wakelock_timer err"); uint32_t curr_freq = MMIO_REG_VAL_FROM_BASE(SCSS_REGISTER_BASE, SCSS_CCU_SYS_CLK_CTL_OFFSET) & (SCSS_CCU_RTC_CLK_DIV_EN | SCSS_RTC_CLK_DIV_MASK); pm_wakelock_init(&rtc_wakelock, RTC_WAKELOCK); // disable interrupt 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); /* Reset initial value only if RTC wasn't enabled at right frequency at * beginning of init */ if (expected_freq != curr_freq) { // Set RTC divider 4096HZ for fast uptade qrk_cxxxx_rtc_clock_frequency(SCSS_RTC_CLK_DIV_4096_HZ); /* set intial RTC value 0 */ MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CLR) = 0; while (0 != MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CCVR)) { MMIO_REG_VAL_FROM_BASE(QRK_RTC_BASE_ADDR, QRK_RTC_CLR) = 0; } } // Set RTC divider 1HZ qrk_cxxxx_rtc_clock_frequency(SCSS_RTC_CLK_DIV_1_HZ); return 0; }
/*! \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; }