Example #1
0
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;
}
Example #2
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;
}
Example #3
0
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;
}
Example #4
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;
}