zephyr/ext/hal/qmsi/drivers/qm_aon_counters.c

151 lines
4.0 KiB
C

/*
* Copyright (c) 2016, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL CORPORATION OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "qm_aon_counters.h"
static void (*callback)(void *) = NULL;
static void *callback_data;
static void pt_reset(const qm_scss_aon_t aonc)
{
static bool first_run = true;
uint32_t aonc_cfg;
/* After POR, it is required to wait for one RTC clock cycle before
* asserting QM_AONPT_CTRL_RST. Note the AON counter is enabled with an
* initial value of 0 at POR.
*/
if (first_run) {
first_run = false;
/* Ensure the AON counter is enabled */
aonc_cfg = QM_SCSS_AON[aonc].aonc_cfg;
QM_SCSS_AON[aonc].aonc_cfg = BIT(0);
while (0 == QM_SCSS_AON[aonc].aonc_cnt) {
}
QM_SCSS_AON[aonc].aonc_cfg = aonc_cfg;
}
QM_SCSS_AON[aonc].aonpt_ctrl |= BIT(1);
}
QM_ISR_DECLARE(qm_aonpt_isr_0)
{
if (callback) {
(*callback)(callback_data);
}
QM_SCSS_AON[0].aonpt_ctrl |= BIT(0); /* Clear pending interrupts */
QM_ISR_EOI(QM_IRQ_AONPT_0_VECTOR);
}
int qm_aonc_enable(const qm_scss_aon_t aonc)
{
QM_CHECK(aonc < QM_SCSS_AON_NUM, -EINVAL);
QM_SCSS_AON[aonc].aonc_cfg = 0x1;
return 0;
}
int qm_aonc_disable(const qm_scss_aon_t aonc)
{
QM_CHECK(aonc < QM_SCSS_AON_NUM, -EINVAL);
QM_SCSS_AON[aonc].aonc_cfg = 0x0;
return 0;
}
int qm_aonc_get_value(const qm_scss_aon_t aonc, uint32_t * const val)
{
QM_CHECK(aonc < QM_SCSS_AON_NUM, -EINVAL);
QM_CHECK(val != NULL, -EINVAL);
*val = QM_SCSS_AON[aonc].aonc_cnt;
return 0;
}
int qm_aonpt_set_config(const qm_scss_aon_t aonc,
const qm_aonpt_config_t *const cfg)
{
QM_CHECK(aonc < QM_SCSS_AON_NUM, -EINVAL);
QM_CHECK(cfg != NULL, -EINVAL);
QM_SCSS_AON[aonc].aonpt_ctrl |= BIT(0); /* Clear pending interrupts */
QM_SCSS_AON[aonc].aonpt_cfg = cfg->count;
if (cfg->int_en) {
callback = cfg->callback;
callback_data = cfg->callback_data;
} else {
callback = NULL;
}
pt_reset(aonc);
return 0;
}
int qm_aonpt_get_value(const qm_scss_aon_t aonc, uint32_t *const val)
{
QM_CHECK(aonc < QM_SCSS_AON_NUM, -EINVAL);
QM_CHECK(val != NULL, -EINVAL);
*val = QM_SCSS_AON[aonc].aonpt_cnt;
return 0;
}
int qm_aonpt_get_status(const qm_scss_aon_t aonc, bool *const status)
{
QM_CHECK(aonc < QM_SCSS_AON_NUM, -EINVAL);
QM_CHECK(status != NULL, -EINVAL);
*status = QM_SCSS_AON[aonc].aonpt_stat & BIT(0);
return 0;
}
int qm_aonpt_clear(const qm_scss_aon_t aonc)
{
QM_CHECK(aonc < QM_SCSS_AON_NUM, -EINVAL);
QM_SCSS_AON[aonc].aonpt_ctrl |= BIT(0);
return 0;
}
int qm_aonpt_reset(const qm_scss_aon_t aonc)
{
QM_CHECK(aonc < QM_SCSS_AON_NUM, -EINVAL);
pt_reset(aonc);
return 0;
}