| /* |
| * 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; |
| } |