1422 lines
44 KiB
C
1422 lines
44 KiB
C
/**
|
||
* @file sdrv_ckgen_hw_access.c
|
||
* @brief taishan ckgen hw access source file.
|
||
*
|
||
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
|
||
* All rights reserved.
|
||
*/
|
||
|
||
#include <compiler.h>
|
||
#include <bits.h>
|
||
#include "sdrv_ckgen_hw_access.h"
|
||
#include "sdrv_ckgen_common.h"
|
||
|
||
bool sdrv_ckgen_ip_slice_hardware_gated(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_IP_CTL_BASE(base, id);
|
||
|
||
return !BIT_SET(readl(ctrl_reg), CKGEN_IP_CTL_HW_CG_EN_STATUS);
|
||
}
|
||
|
||
void sdrv_ckgen_ip_slice_hardware_gate_enable(uint32_t base, uint32_t id, bool en)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_IP_CTL_BASE(base, id);
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_IP_CTL_HW_DIS_EN, 1, en);
|
||
}
|
||
|
||
bool sdrv_ckgen_core_slice_hardware_gated(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_CORE_CTL_BASE(base, id);
|
||
|
||
return !BIT_SET(readl(ctrl_reg), CKGEN_CORE_CTL_HW_CG_EN_STATUS);
|
||
}
|
||
|
||
void sdrv_ckgen_core_slice_hardware_gate_enable(uint32_t base, uint32_t id, bool en)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_CORE_CTL_BASE(base, id);
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_CORE_CTL_HW_DIS_EN, 1, en);
|
||
}
|
||
|
||
bool sdrv_ckgen_bus_slice_hardware_gated(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_BUS_CTL_BASE(base, id);
|
||
|
||
return !BIT_SET(readl(ctrl_reg), CKGEN_BUS_CTL_HW_CG_EN_STATUS);
|
||
}
|
||
|
||
void sdrv_ckgen_bus_slice_hardware_gate_enable(uint32_t base, uint32_t id, bool en)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_BUS_CTL_BASE(base, id);
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_BUS_CTL_HW_DIS_EN, 1, en);
|
||
}
|
||
|
||
bool sdrv_ckgen_ip_slice_gated(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_IP_CTL_BASE(base, id);
|
||
|
||
return BITS_SHIFT(readl(ctrl_reg), 30, 29) ? false : true;
|
||
}
|
||
|
||
bool sdrv_ckgen_core_slice_gated(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_CORE_CTL_BASE(base, id);
|
||
|
||
return BITS_SHIFT(readl(ctrl_reg), 30, 29) ? false : true;
|
||
}
|
||
|
||
bool sdrv_ckgen_bus_slice_gated(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_BUS_CTL_BASE(base, id);
|
||
|
||
return BITS_SHIFT(readl(ctrl_reg), 30, 29) ? false : true;
|
||
}
|
||
|
||
int sdrv_ckgen_ip_slice_set_mux(uint32_t base, uint32_t id, uint8_t mux)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_IP_CTL_BASE(base, id);
|
||
uint32_t ctrl_val = readl(ctrl_reg);
|
||
|
||
if (mux == sdrv_ckgen_ip_slice_get_mux(base, id)) {
|
||
|
||
if ((mux == 4) && BIT(ctrl_val, CKGEN_IP_CTL_MAIN_EN_STATUS)
|
||
&& !BIT(ctrl_val, CKGEN_IP_CTL_D0_ACTIVE)) {
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_IP_CTL_PRE_EN, 1u, 0u);
|
||
|
||
if (sdrv_ckgen_wait(ctrl_reg, CKGEN_IP_CTL_PRE_EN_STATUS,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
else {
|
||
return SDRV_CKGEN_SLICE_PRE_STATUS_ERROR;
|
||
}
|
||
}
|
||
else if ((mux < 4) && BIT(ctrl_val, CKGEN_IP_CTL_PRE_EN_STATUS)
|
||
&& BIT(ctrl_val, CKGEN_IP_CTL_D0_ACTIVE)) {
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_IP_CTL_MAIN_EN, 1u, 0u);
|
||
|
||
if (sdrv_ckgen_wait(ctrl_reg, CKGEN_IP_CTL_MAIN_EN_STATUS,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
else {
|
||
return SDRV_CKGEN_SLICE_MAIN_STATUS_ERROR;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* sel ck_in4 first */
|
||
if (BIT(ctrl_val, CKGEN_IP_CTL_D0_ACTIVE)) {
|
||
/* Make sure CG is enabled. */
|
||
RMWREG32(ctrl_reg, CKGEN_IP_CTL_MAIN_EN, 1u, 1u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_IP_CTL_MAIN_EN_STATUS,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_MAIN_STATUS_ERROR;
|
||
}
|
||
|
||
/* set clk_src_sel[2] to 1’b1. */
|
||
RMWREG32(ctrl_reg, CKGEN_IP_CTL_SRC_SEL_CKIN4, 1u, 1u);
|
||
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_IP_CTL_D0_ACTIVE,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_D0_ACTIVE_ERROR;
|
||
}
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_IP_CTL_PRE_EN, 1u, 0u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_IP_CTL_PRE_EN_STATUS,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_PRE_STATUS_ERROR;
|
||
}
|
||
}
|
||
|
||
/* sel ck_in0 to ck_in3 */
|
||
if (mux < 4) {
|
||
/*set reg_pre_en to 1’b0, wait pre_en_ack to 1’b0.*/
|
||
RMWREG32(ctrl_reg, CKGEN_IP_CTL_PRE_EN, 1u, 0u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_IP_CTL_PRE_EN_STATUS,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_PRE_STATUS_ERROR;
|
||
}
|
||
|
||
/* set clk_src_sel[1:0] to select the clock.*/
|
||
RMWREG32(ctrl_reg, CKGEN_IP_CTL_SRC_SEL_LSB, 2u, mux);
|
||
|
||
/*set reg_pre_en to 1’b1, wait pre_en_ack to 1’b1.*/
|
||
RMWREG32(ctrl_reg, CKGEN_IP_CTL_PRE_EN, 1u, 1u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_IP_CTL_PRE_EN_STATUS,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_PRE_STATUS_ERROR;
|
||
}
|
||
|
||
/* set clk_src_sel[2] to 1’b0. */
|
||
RMWREG32(ctrl_reg, CKGEN_IP_CTL_SRC_SEL_CKIN4, 1u, 0u);
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_IP_CTL_MAIN_EN, 1u, 0u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_IP_CTL_MAIN_EN_STATUS,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_MAIN_STATUS_ERROR;
|
||
}
|
||
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_IP_CTL_D0_ACTIVE,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_D0_ACTIVE_ERROR;
|
||
}
|
||
}
|
||
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
|
||
uint8_t sdrv_ckgen_ip_slice_get_mux(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_IP_CTL_BASE(base, id);
|
||
uint32_t ret = (readl(ctrl_reg) >> CKGEN_IP_CTL_SRC_SEL_LSB) & CKGEN_IP_CTL_SRC_SEL_MASK;
|
||
|
||
if (ret & (1 << CKGEN_IP_CTL_SRC_SEL_CKIN4)) {
|
||
ret = 1 << CKGEN_IP_CTL_SRC_SEL_CKIN4;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
int sdrv_ckgen_ip_slice_set_div(uint32_t base, uint32_t id, uint32_t div)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_IP_CTL_BASE(base, id);
|
||
uint32_t ctrl_val = readl(ctrl_reg);
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_IP_CTL_DIV_NUM_LSB, 8u, div - 1u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_IP_CTL_DIV_CHG_BUSY,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_DIV_CHG_BUSY;
|
||
}
|
||
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
|
||
uint32_t sdrv_ckgen_ip_slice_get_div(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_IP_CTL_BASE(base, id);
|
||
return (readl(ctrl_reg) >> CKGEN_IP_CTL_DIV_NUM_LSB) & CKGEN_IP_CTL_DIV_NUM_MASK;
|
||
}
|
||
|
||
int sdrv_ckgen_core_slice_set_mux(uint32_t base, uint32_t id, uint8_t mux)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_CORE_CTL_BASE(base, id);
|
||
uint32_t ctrl_val = readl(ctrl_reg);
|
||
|
||
if (mux == sdrv_ckgen_core_slice_get_mux(base, id)) {
|
||
|
||
if ((mux == 4) && BIT(ctrl_val, CKGEN_CORE_CTL_MAIN_EN_STATUS)
|
||
&& !BIT(ctrl_val, CKGEN_CORE_CTL_D0_ACTIVE)) {
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_CORE_CTL_PRE_EN, 1u, 0u);
|
||
|
||
if (sdrv_ckgen_wait(ctrl_reg, CKGEN_CORE_CTL_PRE_EN_STATUS,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
else {
|
||
return SDRV_CKGEN_SLICE_PRE_STATUS_ERROR;
|
||
}
|
||
}
|
||
else if ((mux < 4) && BIT(ctrl_val, CKGEN_CORE_CTL_PRE_EN_STATUS)
|
||
&& BIT(ctrl_val, CKGEN_CORE_CTL_D0_ACTIVE)) {
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_CORE_CTL_MAIN_EN, 1u, 0u);
|
||
|
||
if (sdrv_ckgen_wait(ctrl_reg, CKGEN_CORE_CTL_MAIN_EN_STATUS,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
else {
|
||
return SDRV_CKGEN_SLICE_MAIN_STATUS_ERROR;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* sel ck_in4 first */
|
||
if (BIT(ctrl_val, CKGEN_CORE_CTL_D0_ACTIVE)) {
|
||
/* Make sure CG is enabled. */
|
||
RMWREG32(ctrl_reg, CKGEN_CORE_CTL_MAIN_EN, 1u, 1u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_CORE_CTL_MAIN_EN_STATUS,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_MAIN_STATUS_ERROR;
|
||
}
|
||
|
||
/* set clk_src_sel[2] to 1’b1. */
|
||
RMWREG32(ctrl_reg, CKGEN_CORE_CTL_SRC_SEL_CKIN4, 1u, 1u);
|
||
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_CORE_CTL_D0_ACTIVE,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_D0_ACTIVE_ERROR;
|
||
}
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_CORE_CTL_PRE_EN, 1u, 0u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_CORE_CTL_PRE_EN_STATUS,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_PRE_STATUS_ERROR;
|
||
}
|
||
}
|
||
|
||
/* sel ck_in0 to ck_in3 */
|
||
if (mux < 4) {
|
||
/*set reg_pre_en to 1’b0, wait pre_en_ack to 1’b0.*/
|
||
RMWREG32(ctrl_reg, CKGEN_CORE_CTL_PRE_EN, 1u, 0u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_CORE_CTL_PRE_EN_STATUS,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_PRE_STATUS_ERROR;
|
||
}
|
||
|
||
/* set clk_src_sel[1:0] to select the clock.*/
|
||
RMWREG32(ctrl_reg, CKGEN_CORE_CTL_SRC_SEL_LSB, 2u, mux);
|
||
|
||
/*set reg_pre_en to 1’b1, wait pre_en_ack to 1’b1.*/
|
||
RMWREG32(ctrl_reg, CKGEN_CORE_CTL_PRE_EN, 1u, 1u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_CORE_CTL_PRE_EN_STATUS,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_PRE_STATUS_ERROR;
|
||
}
|
||
|
||
/* set clk_src_sel[2] to 1’b0. */
|
||
RMWREG32(ctrl_reg, CKGEN_CORE_CTL_SRC_SEL_CKIN4, 1u, 0u);
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_CORE_CTL_MAIN_EN, 1u, 0u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_CORE_CTL_MAIN_EN_STATUS,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_MAIN_STATUS_ERROR;
|
||
}
|
||
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_CORE_CTL_D0_ACTIVE,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_D0_ACTIVE_ERROR;
|
||
}
|
||
}
|
||
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
|
||
uint8_t sdrv_ckgen_core_slice_get_mux(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_CORE_CTL_BASE(base, id);
|
||
uint32_t src_sel;
|
||
uint8_t mux;
|
||
|
||
src_sel = (readl(ctrl_reg) >> CKGEN_CORE_CTL_SRC_SEL_LSB) & CKGEN_CORE_CTL_SRC_SEL_MASK;
|
||
|
||
/* sel ck_in4 */
|
||
if (src_sel & (1u << 2u)) {
|
||
mux = 4;
|
||
}
|
||
/* sel ck_in0 ~ ck_in3 */
|
||
else {
|
||
mux = src_sel & 0x3;
|
||
}
|
||
|
||
return mux;
|
||
}
|
||
|
||
int sdrv_ckgen_core_slice_ena_pre_div(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_CORE_CTL_BASE(base, id);
|
||
uint32_t ctrl_val = readl(ctrl_reg);
|
||
|
||
/*set reg_pre_en to 1’b1, wait pre_en_ack to 1’b1.*/
|
||
RMWREG32(ctrl_reg, CKGEN_CORE_CTL_PRE_EN, 1u, 1u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_CORE_CTL_PRE_EN_STATUS,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_PRE_STATUS_ERROR;
|
||
}
|
||
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
|
||
int sdrv_ckgen_core_slice_set_div(uint32_t base, uint32_t id, uint32_t div)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_CORE_CTL_BASE(base, id);
|
||
uint32_t ctrl_val = readl(ctrl_reg);
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_CORE_CTL_DIV_NUM_LSB, 5u, div - 1u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_CORE_CTL_DIV_CHG_BUSY,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_DIV_CHG_BUSY;
|
||
}
|
||
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
|
||
uint32_t sdrv_ckgen_core_slice_get_div(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_CORE_CTL_BASE(base, id);
|
||
return (readl(ctrl_reg) >> CKGEN_CORE_CTL_DIV_NUM_LSB) & CKGEN_CORE_CTL_DIV_NUM_MASK;
|
||
}
|
||
|
||
int sdrv_ckgen_bus_slice_set_post_mux(uint32_t base, uint32_t id, uint8_t mux)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_BUS_CTL_BASE(base, id);
|
||
|
||
/* Make sure CG is enabled. */
|
||
if (mux == 1) {
|
||
RMWREG32(ctrl_reg, CKGEN_BUS_CTL_MAIN_EN, 1u, 1u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_BUS_CTL_MAIN_EN_STATUS,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_MAIN_STATUS_ERROR;
|
||
}
|
||
}
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_BUS_CTL_SRC_SEL_CKOUT, 1u, mux);
|
||
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_BUS_CTL_POST_MUX_D0_ACTIVE,
|
||
!mux, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_POST_D0_ACTIVE_ERROR;
|
||
}
|
||
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
|
||
int sdrv_ckgen_bus_slice_set_pre_mux(uint32_t base, uint32_t id, uint8_t mux)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_BUS_CTL_BASE(base, id);
|
||
uint32_t ctrl_val = readl(ctrl_reg);
|
||
|
||
if (mux == sdrv_ckgen_bus_slice_get_pre_mux(base, id)) {
|
||
|
||
if ((mux == 4) && BIT(ctrl_val, CKGEN_BUS_CTL_MAIN_EN_STATUS)
|
||
&& !BIT(ctrl_val, CKGEN_BUS_CTL_PRE_MUX_D0_ACTIVE)) {
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_BUS_CTL_PRE_EN, 1u, 0u);
|
||
|
||
if (sdrv_ckgen_wait(ctrl_reg, CKGEN_BUS_CTL_PRE_EN_STATUS,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
else {
|
||
return SDRV_CKGEN_SLICE_PRE_STATUS_ERROR;
|
||
}
|
||
}
|
||
else if ((mux < 4) && BIT(ctrl_val, CKGEN_BUS_CTL_PRE_EN_STATUS)
|
||
&& BIT(ctrl_val, CKGEN_BUS_CTL_PRE_MUX_D0_ACTIVE)) {
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_BUS_CTL_SRC_SEL_CKOUT, 1u, 0u);
|
||
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_BUS_CTL_POST_MUX_D0_ACTIVE,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_D0_ACTIVE_ERROR;
|
||
}
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_BUS_CTL_MAIN_EN, 1u, 0u);
|
||
|
||
if (sdrv_ckgen_wait(ctrl_reg, CKGEN_BUS_CTL_MAIN_EN_STATUS,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
else {
|
||
return SDRV_CKGEN_SLICE_MAIN_STATUS_ERROR;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* sel ck_in4 first */
|
||
if (BIT(ctrl_val, CKGEN_BUS_CTL_PRE_MUX_D0_ACTIVE)) {
|
||
/* Make sure CG is enabled. */
|
||
RMWREG32(ctrl_reg, CKGEN_BUS_CTL_MAIN_EN, 1u, 1u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_BUS_CTL_MAIN_EN_STATUS,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_MAIN_STATUS_ERROR;
|
||
}
|
||
|
||
/* set clk_src_sel[2] to 1’b1. */
|
||
RMWREG32(ctrl_reg, CKGEN_BUS_CTL_SRC_SEL_CKIN4, 1u, 1u);
|
||
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_BUS_CTL_PRE_MUX_D0_ACTIVE,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_D0_ACTIVE_ERROR;
|
||
}
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_BUS_CTL_PRE_EN, 1u, 0u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_BUS_CTL_PRE_EN_STATUS,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_PRE_STATUS_ERROR;
|
||
}
|
||
}
|
||
|
||
/* sel ck_in0 to ck_in3 */
|
||
if (mux < 4) {
|
||
/*set reg_pre_en to 1’b0, wait pre_en_ack to 1’b0.*/
|
||
RMWREG32(ctrl_reg, CKGEN_BUS_CTL_PRE_EN, 1u, 0u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_BUS_CTL_PRE_EN_STATUS,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_PRE_STATUS_ERROR;
|
||
}
|
||
|
||
/* set clk_src_sel[1:0] to select the clock.*/
|
||
RMWREG32(ctrl_reg, CKGEN_BUS_CTL_SRC_SEL_LSB, 2u, mux);
|
||
|
||
/*set reg_pre_en to 1’b1, wait pre_en_ack to 1’b1.*/
|
||
RMWREG32(ctrl_reg, CKGEN_BUS_CTL_PRE_EN, 1u, 1u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_BUS_CTL_PRE_EN_STATUS,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_PRE_STATUS_ERROR;
|
||
}
|
||
|
||
/* set clk_src_sel[2] to 1’b0. */
|
||
RMWREG32(ctrl_reg, CKGEN_BUS_CTL_SRC_SEL_CKIN4, 1u, 0u);
|
||
|
||
/* if post d0 is 1, need change to 0 */
|
||
RMWREG32(ctrl_reg, CKGEN_BUS_CTL_SRC_SEL_CKOUT, 1u, 0u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_BUS_CTL_POST_MUX_D0_ACTIVE,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_D0_ACTIVE_ERROR;
|
||
}
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_BUS_CTL_MAIN_EN, 1u, 0u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_BUS_CTL_MAIN_EN_STATUS,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_MAIN_STATUS_ERROR;
|
||
}
|
||
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_BUS_CTL_PRE_MUX_D0_ACTIVE,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_D0_ACTIVE_ERROR;
|
||
}
|
||
}
|
||
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
|
||
int sdrv_ckgen_bus_slice_set_pre_div(uint32_t base, uint32_t id, uint32_t div)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_BUS_CTL_BASE(base, id);
|
||
uint32_t ctrl_val = readl(ctrl_reg);
|
||
|
||
RMWREG32(ctrl_reg, CKGEN_BUS_CTL_DIV_NUM_LSB, 5u, div - 1u);
|
||
if (!sdrv_ckgen_wait(ctrl_reg, CKGEN_BUS_CTL_DIV_CHG_BUSY,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_DIV_CHG_BUSY;
|
||
}
|
||
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
|
||
int sdrv_ckgen_bus_slice_set_sf_post_div(uint32_t base, uint32_t id, uint32_t ratio)
|
||
{
|
||
if (id == 0) {
|
||
RMWREG32(base + CKGEN_RES, CKGEN_RES_RS_SF_RATIO_SEL, 1u, ratio);
|
||
}
|
||
else {
|
||
RMWREG32(base + CKGEN_RES, CKGEN_RES_RS_SP_RATIO_SEL, 1u, ratio);
|
||
}
|
||
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
|
||
int sdrv_ckgen_bus_slice_set_mnpq_div(uint32_t base, uint32_t id,
|
||
uint8_t type, uint32_t div)
|
||
{
|
||
uint32_t sync_ctrl_reg = CKGEN_BUS_SYNC_CTL_BASE(base, id);
|
||
uint32_t div_offset;
|
||
uint32_t div_busy_offset;
|
||
|
||
div_offset = type * 4u + CKGEN_BUS_SYNC_CTL_DIV_M_LSB;
|
||
div_busy_offset = type + CKGEN_BUS_SYNC_CTL_DIV_CHG_BUSY_LSB;
|
||
|
||
RMWREG32(sync_ctrl_reg, div_offset, 4u, div - 1u);
|
||
if (!sdrv_ckgen_wait(sync_ctrl_reg, div_busy_offset,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return SDRV_CKGEN_SLICE_DIV_CHG_BUSY;
|
||
}
|
||
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
|
||
int sdrv_ckgen_bus_slice_set_mnpq_div_onetime(uint32_t base, uint32_t id, uint8_t div_m,
|
||
uint8_t div_n, uint8_t div_p, uint8_t div_q)
|
||
{
|
||
uint32_t sync_ctrl_reg = CKGEN_BUS_SYNC_CTL_BASE(base, id);
|
||
uint32_t div_flag = 0u;
|
||
volatile int32_t times_out = (int32_t)CKGEN_WAIT_TIME;
|
||
uint32_t div_mnpq = readl(sync_ctrl_reg) & 0xffffu;
|
||
|
||
if (div_m > 0u) {
|
||
div_flag = 1u << CKGEN_HW_BUS_DIV_M;
|
||
div_mnpq &= ~((uint32_t)0xfu << (CKGEN_BUS_SYNC_CTL_DIV_M_LSB));
|
||
div_mnpq |= (((uint32_t)div_m - 1u) & 0xfu) << CKGEN_BUS_SYNC_CTL_DIV_M_LSB;
|
||
}
|
||
|
||
if (div_n > 0u) {
|
||
div_flag |= 1u << CKGEN_HW_BUS_DIV_N;
|
||
div_mnpq &= ~((uint32_t)0xfu << (CKGEN_BUS_SYNC_CTL_DIV_N_LSB));
|
||
div_mnpq |= (((uint32_t)div_n - 1u) & 0xfu) << CKGEN_BUS_SYNC_CTL_DIV_N_LSB;
|
||
}
|
||
|
||
if (div_p > 0u) {
|
||
div_flag |= 1u << CKGEN_HW_BUS_DIV_P;
|
||
div_mnpq &= ~((uint32_t)0xfu << (CKGEN_BUS_SYNC_CTL_DIV_P_LSB));
|
||
div_mnpq |= (((uint32_t)div_p - 1u) & 0xfu) << CKGEN_BUS_SYNC_CTL_DIV_P_LSB;
|
||
}
|
||
|
||
if (div_q > 0u) {
|
||
div_flag |= 1u << CKGEN_HW_BUS_DIV_Q;
|
||
div_mnpq &= ~((uint32_t)0xfu << (CKGEN_BUS_SYNC_CTL_DIV_Q_LSB));
|
||
div_mnpq |= (((uint32_t)div_q - 1u) & 0xfu) << CKGEN_BUS_SYNC_CTL_DIV_Q_LSB;
|
||
}
|
||
|
||
if (div_flag) {
|
||
RMWREG32(sync_ctrl_reg, CKGEN_BUS_SYNC_CTL_DIV_M_LSB, 16u, div_mnpq);
|
||
|
||
while ((times_out > 0) &&
|
||
(0u != ((readl(sync_ctrl_reg) >> CKGEN_BUS_SYNC_CTL_DIV_CHG_BUSY_LSB)
|
||
& div_flag))) {
|
||
times_out--;
|
||
}
|
||
|
||
if (times_out <= 0) {
|
||
return SDRV_CKGEN_SLICE_DIV_CHG_BUSY;
|
||
}
|
||
}
|
||
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
|
||
uint8_t sdrv_ckgen_bus_slice_get_pre_mux(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_BUS_CTL_BASE(base, id);
|
||
uint32_t src_sel;
|
||
uint8_t mux;
|
||
|
||
src_sel = (readl(ctrl_reg) >> CKGEN_BUS_CTL_SRC_SEL_LSB) & CKGEN_BUS_CTL_SRC_SEL_MASK;
|
||
|
||
/* sel ck_in4 */
|
||
if (src_sel & (1u << 2u)) {
|
||
mux = 4;
|
||
}
|
||
/* sel ck_in0 ~ ck_in3 */
|
||
else {
|
||
mux = src_sel & 0x3;
|
||
}
|
||
|
||
return mux;
|
||
}
|
||
|
||
uint32_t sdrv_ckgen_bus_slice_get_pre_div(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_BUS_CTL_BASE(base, id);
|
||
return (readl(ctrl_reg) >> CKGEN_BUS_CTL_DIV_NUM_LSB) & CKGEN_BUS_CTL_DIV_NUM_MASK;
|
||
}
|
||
|
||
uint32_t sdrv_ckgen_bus_slice_get_mnpq_div(uint32_t base, uint32_t id, uint8_t type)
|
||
{
|
||
uint32_t sync_ctrl = CKGEN_BUS_SYNC_CTL_BASE(base, id);
|
||
uint32_t val;
|
||
uint32_t div_offset;
|
||
|
||
val = readl(sync_ctrl);
|
||
div_offset = type * 4u + CKGEN_BUS_SYNC_CTL_DIV_M_LSB;
|
||
return (val >> div_offset) & CKGEN_BUS_SYNC_CTL_DIV_MASK;
|
||
}
|
||
|
||
int sdrv_ckgen_xcg_set_gate(uint32_t base, uint8_t cg_type, uint32_t id,
|
||
uint8_t lp_mode, bool gating)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_XCG_CTL_BASE(base, id, cg_type);
|
||
RMWREG32(ctrl_reg, CKGEN_CG_CTL_RUN_MODE + lp_mode, 1u, !gating);
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
|
||
bool sdrv_ckgen_xcg_is_gated(uint32_t base, uint8_t cg_type, uint32_t id)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_XCG_CTL_BASE(base, id, cg_type);
|
||
return (readl(ctrl_reg) >> CKGEN_CG_CTL_CG_GATED) & 0x1u;
|
||
}
|
||
|
||
int sdrv_ckgen_xcg_lp_mask(uint32_t base, uint8_t cg_type, uint32_t id, bool mask)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_XCG_CTL_BASE(base, id, cg_type);
|
||
RMWREG32(ctrl_reg, CKGEN_CG_CTL_LP_MASK, 1u, mask);
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
|
||
int sdrv_ckgen_pll_set_gate(uint32_t base, uint32_t id, uint8_t lp_mode, bool gating)
|
||
{
|
||
uint32_t pll_ctrl = CKGEN_PLL_CTL_BASE(base, id);
|
||
|
||
RMWREG32(pll_ctrl, CKGEN_PLL_CTL_IGNORE, 1u, 0u);
|
||
RMWREG32(pll_ctrl, CKGEN_PLL_CTL_RUN_MODE + lp_mode, 1u, !gating);
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
|
||
int sdrv_ckgen_pll_set_pd(uint32_t base, uint32_t id, uint8_t lp_mode, bool pd_state)
|
||
{
|
||
RMWREG32(CKGEN_PLL_CTL_BASE(base, id),
|
||
CKGEN_PLL_PD_RUN_MODE + lp_mode, 1u, pd_state);
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
|
||
int sdrv_ckgen_xtal_set_gate(uint32_t base, uint8_t lp_mode, bool gating)
|
||
{
|
||
uint32_t xtal_ctrl = base + CKGEN_XTAL_CTL;
|
||
|
||
RMWREG32(xtal_ctrl, CKGEN_XTAL_CTL_IGNORE, 1u, 0u);
|
||
RMWREG32(xtal_ctrl, CKGEN_XTAL_CTL_RUN_MODE + lp_mode, 1u, !gating);
|
||
return SDRV_STATUS_OK;
|
||
}
|
||
|
||
void sdrv_ckgen_enable_rs(uint32_t rs_base, uint8_t rs, bool lock)
|
||
{
|
||
uint32_t rs_val;
|
||
|
||
rs_val = readl(rs_base);
|
||
|
||
rs_val &= ~(CKGEN_RS_RS_MASK << CKGEN_RS_RS_LSB);
|
||
rs_val |= (rs << CKGEN_RS_RS_LSB);
|
||
|
||
rs_val &= ~(1 << CKGEN_RS_LOCK);
|
||
rs_val |= (lock << CKGEN_RS_LOCK);
|
||
|
||
rs_val |= (1 << CKGEN_RS_EN);
|
||
|
||
writel(rs_val, rs_base);
|
||
}
|
||
|
||
void sdrv_ckgen_rs_disable(uint32_t rs_base)
|
||
{
|
||
RMWREG32(rs_base, CKGEN_RS_EN, 1u, 0u);
|
||
}
|
||
|
||
void sdrv_ckgen_ip_cor_int_enable(uint32_t base, uint32_t id, bool en)
|
||
{
|
||
uint32_t cor_en = CKGEN_IP_CLK_COR_EN_BASE(base, (id / 32u));
|
||
RMWREG32(cor_en, (id % 32u), 1u, en);
|
||
}
|
||
|
||
void sdrv_ckgen_ip_unc_int_enable(uint32_t base, uint32_t id, bool en)
|
||
{
|
||
uint32_t unc_en = CKGEN_IP_CLK_UNC_EN_BASE(base, (id / 32u));
|
||
RMWREG32(unc_en, (id % 32u), 1u, en);
|
||
}
|
||
|
||
bool sdrv_ckgen_ip_get_int_state(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t state = CKGEN_IP_CLK_INT_STA_BASE(base, (id / 32u));
|
||
return !!(readl(state) >> (id % 32u));
|
||
}
|
||
|
||
void sdrv_ckgen_ip_clear_int_state(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t reg = CKGEN_IP_CLK_INT_STA_BASE(base, (id / 32u));
|
||
RMWREG32(reg, (id % 32u), 1u, 0u);
|
||
}
|
||
|
||
void sdrv_ckgen_bus_cor_int_enable(uint32_t base, uint32_t id, bool en)
|
||
{
|
||
uint32_t cor_en = CKGEN_BUS_CLK_COR_EN_BASE(base, (id / 32u));
|
||
RMWREG32(cor_en, (id % 32u), 1u, en);
|
||
}
|
||
|
||
void sdrv_ckgen_bus_unc_int_enable(uint32_t base, uint32_t id, bool en)
|
||
{
|
||
uint32_t unc_en = CKGEN_BUS_CLK_UNC_EN_BASE(base, (id / 32u));
|
||
RMWREG32(unc_en, (id % 32u), 1u, en);
|
||
}
|
||
|
||
bool sdrv_ckgen_bus_get_int_state(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t state = CKGEN_BUS_CLK_INT_STA_BASE(base, (id / 32u));
|
||
return !!(readl(state) >> (id % 32u));
|
||
}
|
||
|
||
void sdrv_ckgen_bus_clear_int_state(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t reg = CKGEN_BUS_CLK_INT_STA_BASE(base, (id / 32u));
|
||
RMWREG32(reg, (id % 32u), 1u, 0u);
|
||
}
|
||
|
||
void sdrv_ckgen_core_cor_int_enable(uint32_t base, uint32_t id, bool en)
|
||
{
|
||
uint32_t cor_en = CKGEN_CORE_CLK_COR_EN_BASE(base, (id / 32u));
|
||
RMWREG32(cor_en, (id % 32u), 1u, en);
|
||
}
|
||
|
||
void sdrv_ckgen_core_unc_int_enable(uint32_t base, uint32_t id, bool en)
|
||
{
|
||
uint32_t unc_en = CKGEN_CORE_CLK_UNC_EN_BASE(base, (id / 32u));
|
||
RMWREG32(unc_en, (id % 32u), 1u, en);
|
||
}
|
||
|
||
bool sdrv_ckgen_core_get_int_state(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t state = CKGEN_CORE_CLK_INT_STA_BASE(base, (id / 32u));
|
||
return !!(readl(state) >> (id % 32u));
|
||
}
|
||
|
||
void sdrv_ckgen_core_clear_int_state(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t reg = CKGEN_CORE_CLK_INT_STA_BASE(base, (id / 32u));
|
||
RMWREG32(reg, (id % 32u), 1u, 0u);
|
||
}
|
||
|
||
void sdrv_ckgen_xcg_cor_int_enable(uint32_t base, uint8_t type, uint32_t id, bool en)
|
||
{
|
||
uint32_t cor_en = CKGEN_XCG_COR_EN_BASE(base, (id/ 32u), type);
|
||
RMWREG32(cor_en, (id % 32u), 1u, en);
|
||
}
|
||
|
||
void sdrv_ckgen_xcg_unc_int_enable(uint32_t base, uint8_t type, uint32_t id, bool en)
|
||
{
|
||
uint32_t unc_en = CKGEN_XCG_UNC_EN_BASE(base, (id / 32u), type);
|
||
RMWREG32(unc_en, (id % 32u), 1u, en);
|
||
}
|
||
|
||
bool sdrv_ckgen_xcg_get_int_state(uint32_t base, uint8_t type, uint32_t id)
|
||
{
|
||
uint32_t state = CKGEN_XCG_INT_STA_BASE(base, (id / 32u), type);
|
||
return !!(readl(state) >> (id % 32u));
|
||
}
|
||
|
||
void sdrv_ckgen_xcg_clear_int_state(uint32_t base, uint8_t type, uint32_t id)
|
||
{
|
||
uint32_t state = CKGEN_XCG_INT_STA_BASE(base, (id / 32u), type);
|
||
RMWREG32(state, (id % 32u), 1u, 0u);
|
||
}
|
||
|
||
static uint32_t sdrv_ckgen_mon_calc_freq(uint32_t base, uint32_t freq_mon, uint8_t div_a_b)
|
||
{
|
||
uint32_t glb_ctrl_val;
|
||
uint32_t div_a_b_num;
|
||
uint32_t rate = 0;
|
||
|
||
glb_ctrl_val = readl(CKGEN_GLB_CTL_BASE(base));
|
||
|
||
if (div_a_b) {
|
||
/* 24M divb */
|
||
div_a_b_num = (glb_ctrl_val >> CKGEN_GLB_CTL_24M_DIVB_NUM_LSB) & CKGEN_GLB_CTL_24M_DIVB_NUM_MASK;
|
||
}
|
||
else {
|
||
/* 24M diva */
|
||
div_a_b_num = (glb_ctrl_val >> CKGEN_GLB_CTL_24M_DIVA_NUM_LSB) & CKGEN_GLB_CTL_24M_DIVA_NUM_MASK;
|
||
}
|
||
|
||
rate = 12000000 / (div_a_b_num + 1);
|
||
rate = rate * freq_mon;
|
||
|
||
return rate;
|
||
}
|
||
|
||
__UNUSED static void sdrv_ckgen_xcg_debug_enable(uint32_t base, uint8_t cg_type, uint32_t id, bool en)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_XCG_CTL_BASE(base, id, cg_type);;
|
||
RMWREG32(ctrl_reg, CKGEN_CG_CTL_DBG_EN, 1u, en);
|
||
}
|
||
|
||
static void sdrv_ckgen_xcg_amon_enable(uint32_t base, uint8_t cg_type, uint32_t id, bool en)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_XCG_CTL_BASE(base, id, cg_type);;
|
||
RMWREG32(ctrl_reg, CKGEN_CG_CTL_ACTIVE_MON_EN, 1u, en);
|
||
}
|
||
|
||
static uint8_t sdrv_ckgen_xcg_get_amon_state(uint32_t base, uint8_t cg_type, uint32_t id)
|
||
{
|
||
uint32_t ctrl_reg = CKGEN_XCG_CTL_BASE(base, id, cg_type);;
|
||
return (readl(ctrl_reg) >> CKGEN_CG_CTL_ACTIVE_MON_STA) & 0x1u;
|
||
}
|
||
|
||
static void sdrv_ckgen_pll_mon_enable(uint32_t base, uint32_t id, uint32_t tout)
|
||
{
|
||
uint32_t mon_ctrl = CKGEN_PLL_MON_CTL_BASE(base, id);
|
||
RMWREG32(mon_ctrl, CKGEN_PLL_MON_CTL_TOUT_VAL_LSB, 16u, tout);
|
||
RMWREG32(mon_ctrl, CKGEN_PLL_MON_CTL_EN, 1u, 1u);
|
||
}
|
||
|
||
static void sdrv_ckgen_pll_mon_disable(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t mon_ctrl = CKGEN_PLL_MON_CTL_BASE(base, id);
|
||
RMWREG32(mon_ctrl, CKGEN_PLL_MON_CTL_EN, 1u, 0u);
|
||
}
|
||
|
||
static uint8_t sdrv_ckgen_pll_mon_get_state(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t mon_ctrl = CKGEN_PLL_MON_CTL_BASE(base, id);
|
||
return (readl(mon_ctrl) >> CKGEN_PLL_MON_CTL_CLK_READY) & 0x1u;
|
||
}
|
||
|
||
static void sdrv_ckgen_xtal_mon_enable(uint32_t base, uint32_t tout)
|
||
{
|
||
uint32_t xtal_mon = base + CKGEN_XTAL_MON_CTL;
|
||
RMWREG32(xtal_mon, CKGEN_XTAL_MON_CTL_TOUT_VAL_LSB, 16u, tout);
|
||
RMWREG32(xtal_mon, CKGEN_XTAL_MON_CTL_EN, 1u, 1u);
|
||
sdrv_ckgen_wait(xtal_mon, CKGEN_XTAL_MON_CTL_EN_STA,
|
||
1u, CKGEN_WAIT_TIME);
|
||
}
|
||
|
||
static void sdrv_ckgen_xtal_mon_disable(uint32_t base)
|
||
{
|
||
uint32_t xtal_mon = base + CKGEN_XTAL_MON_CTL;
|
||
RMWREG32(xtal_mon, CKGEN_XTAL_MON_CTL_EN, 1u, 0u);
|
||
sdrv_ckgen_wait(xtal_mon, CKGEN_XTAL_MON_CTL_EN_STA,
|
||
0u, CKGEN_WAIT_TIME);
|
||
}
|
||
|
||
__UNUSED static uint8_t sdrv_ckgen_xtal_mon_get_rc24m_state(uint32_t base)
|
||
{
|
||
uint32_t xtal_mon = base + CKGEN_XTAL_MON_CTL;
|
||
return (readl(xtal_mon) >> CKGEN_XTAL_MON_CTL_RC24M_ACTIVE) & 0x1u;
|
||
}
|
||
|
||
static uint8_t sdrv_ckgen_xtal_mon_get_xtal_state(uint32_t base)
|
||
{
|
||
uint32_t xtal_mon = base + CKGEN_XTAL_MON_CTL;
|
||
return (readl(xtal_mon) >> CKGEN_XTAL_MON_CTL_XTAL_ACTIVE) & 0x1u;
|
||
}
|
||
|
||
static void sdrv_ckgen_dbg_mon_src_config(uint32_t base, uint8_t src, uint32_t id)
|
||
{
|
||
uint32_t dbg_mon_src = base + CKGEN_DBG_MON_CLK_SRC;
|
||
uint32_t dbg_mon_ctl = base + CKGEN_DBG_MON_CTL;
|
||
|
||
RMWREG32(dbg_mon_src, CKGEN_DBG_MON_CLK_SRC_LSB(src), 8u, id);
|
||
RMWREG32(dbg_mon_ctl, CKGEN_DBG_MON_CTL_CLK_SEL_LSB, 2u, src);
|
||
}
|
||
|
||
static uint32_t sdrv_ckgen_dbg_mon_get_rate(uint32_t base, uint8_t src, uint32_t id)
|
||
{
|
||
uint32_t dbg_mon_ctl = base + CKGEN_DBG_MON_CTL;
|
||
uint32_t mon_ctl = base + CKGEN_MON_CTL;
|
||
uint32_t mon_ctl_val;
|
||
uint32_t freq_mon;
|
||
uint32_t div_a_b;
|
||
uint32_t rate = 0;
|
||
|
||
if (BIT(readl(mon_ctl), CKGEN_MON_CTL_EN)) {
|
||
RMWREG32(mon_ctl, CKGEN_MON_CTL_EN, 1u, 0u);
|
||
if (!sdrv_ckgen_wait(mon_ctl, CKGEN_MON_CTL_EN_STA,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
sdrv_ckgen_dbg_mon_src_config(base, src, id);
|
||
|
||
RMWREG32(dbg_mon_ctl, CKGEN_DBG_MON_CTL_MON_GATING_EN, 1u, 1u);
|
||
|
||
RMWREG32(mon_ctl, CKGEN_MON_CTL_FREQ_LSB, 16u, 0u);
|
||
RMWREG32(mon_ctl, CKGEN_MON_CTL_FREQ_UPD, 1u, 0u);
|
||
|
||
RMWREG32(mon_ctl, CKGEN_MON_CTL_EN, 1u, 1u);
|
||
if (!sdrv_ckgen_wait(mon_ctl, CKGEN_MON_CTL_EN_STA,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
goto dbg_mon_get_ip_rate_out;
|
||
}
|
||
|
||
if (!sdrv_ckgen_wait(mon_ctl, CKGEN_MON_CTL_FREQ_UPD,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
goto dbg_mon_get_ip_rate_out;
|
||
}
|
||
|
||
mon_ctl_val = readl(mon_ctl);
|
||
freq_mon = (mon_ctl_val >> CKGEN_MON_CTL_FREQ_LSB) & CKGEN_MON_CTL_FREQ_MASK;
|
||
div_a_b = (mon_ctl_val >> CKGEN_MON_CTL_SRC_SEL) & 0x1;
|
||
|
||
rate = sdrv_ckgen_mon_calc_freq(base, freq_mon, div_a_b);
|
||
|
||
dbg_mon_get_ip_rate_out:
|
||
|
||
RMWREG32(dbg_mon_ctl, CKGEN_DBG_MON_CTL_MON_GATING_EN, 1u, 0u);
|
||
|
||
RMWREG32(mon_ctl, CKGEN_MON_CTL_EN, 1u, 0u);
|
||
sdrv_ckgen_wait(mon_ctl, CKGEN_MON_CTL_EN_STA,
|
||
0u, CKGEN_WAIT_TIME);
|
||
|
||
return rate;
|
||
}
|
||
|
||
void sdrv_ckgen_set_mon_div(uint32_t base, uint8_t div_type, uint32_t div)
|
||
{
|
||
uint32_t glb_ctrl = CKGEN_GLB_CTL_BASE(base);
|
||
uint32_t div_off;
|
||
uint32_t div_width;
|
||
|
||
if (div_type == CKGEN_MON_DIVA) {
|
||
div_off = CKGEN_GLB_CTL_24M_DIVA_NUM_LSB;
|
||
div_width = 10;
|
||
}
|
||
else if (div_type == CKGEN_MON_DIVB) {
|
||
div_off = CKGEN_GLB_CTL_24M_DIVB_NUM_LSB;
|
||
div_width = 10;
|
||
}
|
||
else if (div_type == CKGEN_MON_DIVC) {
|
||
div_off = CKGEN_GLB_CTL_24M_DIVC_NUM_LSB;
|
||
div_width = 4;
|
||
}
|
||
else {
|
||
return;
|
||
}
|
||
|
||
RMWREG32(glb_ctrl, div_off, div_width, div);
|
||
}
|
||
|
||
uint32_t sdrv_ckgen_ip_mon_get_rate(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t ip_mon_ctrl = CKGEN_IP_MON_CTL_BASE(base, id);
|
||
uint32_t ip_ctrl = CKGEN_IP_CTL_BASE(base, id);
|
||
uint32_t ip_mon_ctrl_val;
|
||
uint32_t freq_mon;
|
||
uint8_t div_a_b;
|
||
uint32_t rate = 0;
|
||
|
||
/* disable ip mon */
|
||
if (BIT(readl(ip_mon_ctrl), CKGEN_IP_MON_CTL_EN)) {
|
||
RMWREG32(ip_mon_ctrl, CKGEN_IP_MON_CTL_EN, 1u, 0u);
|
||
if (!sdrv_ckgen_wait(ip_mon_ctrl, CKGEN_IP_MON_CTL_EN_STA,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
/* clear freq mon */
|
||
RMWREG32(ip_mon_ctrl, CKGEN_IP_MON_CTL_FREQ_LSB, 16u, 0u);
|
||
RMWREG32(ip_mon_ctrl, CKGEN_IP_MON_CTL_FREQ_UPD, 1u, 0u);
|
||
|
||
/* enable ip slice debug */
|
||
RMWREG32(ip_ctrl, CKGEN_IP_CTL_DBG_EN, 1u, 1u);
|
||
|
||
/* enable ip mon */
|
||
RMWREG32(ip_mon_ctrl, CKGEN_IP_MON_CTL_EN, 1u, 1u);
|
||
if (!sdrv_ckgen_wait(ip_mon_ctrl, CKGEN_IP_MON_CTL_EN_STA,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
goto ip_mon_get_rate_out;
|
||
}
|
||
|
||
if (!sdrv_ckgen_wait(ip_mon_ctrl, CKGEN_IP_MON_CTL_FREQ_UPD,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
goto ip_mon_get_rate_out;
|
||
}
|
||
|
||
ip_mon_ctrl_val = readl(ip_mon_ctrl);
|
||
freq_mon = (ip_mon_ctrl_val >> CKGEN_IP_MON_CTL_FREQ_LSB) & CKGEN_IP_MON_CTL_FREQ_MASK;
|
||
div_a_b = (ip_mon_ctrl_val >> CKGEN_IP_MON_CTL_SRC_SEL) & 0x1;
|
||
|
||
rate = sdrv_ckgen_mon_calc_freq(base, freq_mon, div_a_b);
|
||
|
||
ip_mon_get_rate_out:
|
||
|
||
/* disable ip mon */
|
||
RMWREG32(ip_mon_ctrl, CKGEN_IP_MON_CTL_EN, 1u, 0u);
|
||
sdrv_ckgen_wait(ip_mon_ctrl, CKGEN_IP_MON_CTL_EN_STA,
|
||
0u, CKGEN_WAIT_TIME);
|
||
|
||
/* disable ip slice debug */
|
||
RMWREG32(ip_ctrl, CKGEN_IP_CTL_DBG_EN, 1u, 0u);
|
||
|
||
return rate;
|
||
}
|
||
|
||
void sdrv_ckgen_ip_mon_set_thrd(uint32_t base, uint32_t id,
|
||
uint16_t low_thrd, uint16_t high_thrd)
|
||
{
|
||
uint32_t mon_thrd = CKGEN_IP_MON_THRD_BASE(base, id);
|
||
RMWREG32(mon_thrd, CKGEN_IP_MON_THRD_LOW_LSB, 16u, low_thrd);
|
||
RMWREG32(mon_thrd, CKGEN_IP_MON_THRD_HIGH_LSB, 16u, high_thrd);
|
||
}
|
||
|
||
uint32_t sdrv_ckgen_bus_mon_get_rate(uint32_t base, uint32_t id, uint8_t type)
|
||
{
|
||
uint32_t bus_mon_ctrl = CKGEN_BUS_MON_CTL0_BASE(base, id);
|
||
uint32_t bus_mon_out;
|
||
uint32_t bus_ctrl = CKGEN_BUS_CTL_BASE(base, id);
|
||
uint32_t freq_lsb;
|
||
uint32_t out;
|
||
uint32_t bus_mon_ctrl_val;
|
||
uint32_t freq_mon;
|
||
uint8_t div_a_b;
|
||
uint32_t rate = 0;
|
||
|
||
if (type == CKGEN_HW_BUS_DIV_N) {
|
||
out = 1;
|
||
bus_mon_out = CKGEN_BUS_MON_CTL1_BASE(base, id);
|
||
freq_lsb = CKGEN_BUS_MON_CTL1_FREQ1_LSB;
|
||
}
|
||
else if (type == CKGEN_HW_BUS_DIV_P) {
|
||
out = 2;
|
||
bus_mon_out = CKGEN_BUS_MON_CTL2_BASE(base, id);
|
||
freq_lsb = CKGEN_BUS_MON_CTL2_FREQ2_LSB;
|
||
}
|
||
else if (type == CKGEN_HW_BUS_DIV_Q) {
|
||
out = 3;
|
||
bus_mon_out = CKGEN_BUS_MON_CTL2_BASE(base, id);
|
||
freq_lsb = CKGEN_BUS_MON_CTL2_FREQ3_LSB;
|
||
} else {
|
||
out = 0;
|
||
bus_mon_out = CKGEN_BUS_MON_CTL1_BASE(base, id);
|
||
freq_lsb = CKGEN_BUS_MON_CTL1_FREQ0_LSB;
|
||
}
|
||
|
||
/* disable bus mon */
|
||
if (BIT(readl(bus_mon_ctrl), CKGEN_BUS_MON_CTL0_EN)) {
|
||
RMWREG32(bus_mon_ctrl, CKGEN_BUS_MON_CTL0_EN, 1u, 0u);
|
||
if (!sdrv_ckgen_wait(bus_mon_ctrl, CKGEN_BUS_MON_CTL0_EN_STA,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
/* clear freq mon */
|
||
writel(0u, bus_mon_out);
|
||
RMWREG32(bus_mon_ctrl, CKGEN_BUS_MON_CTL0_FREQ_UPD(out), 1u, 0u);
|
||
|
||
/* enable bus slice debug */
|
||
RMWREG32(bus_ctrl, CKGEN_BUS_CTL_DBG_EN, 1u, 1u);
|
||
|
||
/* enable bus mon */
|
||
RMWREG32(bus_mon_ctrl, CKGEN_BUS_MON_CTL0_EN, 1u, 1u);
|
||
if (!sdrv_ckgen_wait(bus_mon_ctrl, CKGEN_BUS_MON_CTL0_EN_STA,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
goto bus_mon_get_rate_out;
|
||
}
|
||
|
||
if (!sdrv_ckgen_wait(bus_mon_ctrl, CKGEN_BUS_MON_CTL0_FREQ_UPD(out),
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
goto bus_mon_get_rate_out;
|
||
}
|
||
|
||
freq_mon = (readl(bus_mon_out) >> freq_lsb) & CKGEN_BUS_MON_CTL_FREQ_MASK;
|
||
|
||
bus_mon_ctrl_val = readl(bus_mon_ctrl);
|
||
div_a_b = (bus_mon_ctrl_val >> CKGEN_BUS_MON_CTL0_SRC_SEL) & 0x1;
|
||
|
||
rate = sdrv_ckgen_mon_calc_freq(base, freq_mon, div_a_b);
|
||
|
||
bus_mon_get_rate_out:
|
||
|
||
/* disable bus mon */
|
||
RMWREG32(bus_mon_ctrl, CKGEN_BUS_MON_CTL0_EN, 1u, 0u);
|
||
sdrv_ckgen_wait(bus_mon_ctrl, CKGEN_BUS_MON_CTL0_EN_STA,
|
||
0u, CKGEN_WAIT_TIME);
|
||
|
||
/* disable bus slice debug */
|
||
RMWREG32(bus_ctrl, CKGEN_BUS_CTL_DBG_EN, 1u, 0u);
|
||
|
||
return rate;
|
||
}
|
||
|
||
void sdrv_ckgen_bus_mon_set_thrd(uint32_t base, uint32_t id, uint8_t type,
|
||
uint16_t low_thrd, uint16_t high_thrd)
|
||
{
|
||
uint32_t bus_mon_thrd;
|
||
|
||
if (type == CKGEN_HW_BUS_DIV_N) {
|
||
bus_mon_thrd = CKGEN_BUS_MON_THRD1_BASE(base, id);
|
||
}
|
||
else if (type == CKGEN_HW_BUS_DIV_P) {
|
||
bus_mon_thrd = CKGEN_BUS_MON_THRD2_BASE(base, id);
|
||
}
|
||
else if (type == CKGEN_HW_BUS_DIV_Q) {
|
||
bus_mon_thrd = CKGEN_BUS_MON_THRD3_BASE(base, id);
|
||
} else {
|
||
bus_mon_thrd = CKGEN_BUS_MON_THRD0_BASE(base, id);
|
||
}
|
||
|
||
RMWREG32(bus_mon_thrd, CKGEN_BUS_MON_THRD_LOW_LSB, 16u, low_thrd);
|
||
RMWREG32(bus_mon_thrd, CKGEN_BUS_MON_THRD_HIGH_LSB, 16u, high_thrd);
|
||
}
|
||
|
||
uint32_t sdrv_ckgen_core_mon_get_rate(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t core_mon_ctrl = CKGEN_CORE_MON_CTL_BASE(base, id);
|
||
uint32_t core_ctrl = CKGEN_CORE_CTL_BASE(base, id);
|
||
uint32_t core_mon_ctrl_val;
|
||
uint32_t freq_mon;
|
||
uint8_t div_a_b;
|
||
uint32_t rate = 0;
|
||
|
||
/* disable core mon */
|
||
if (BIT(readl(core_mon_ctrl), CKGEN_CORE_MON_CTL_EN)) {
|
||
RMWREG32(core_mon_ctrl, CKGEN_CORE_MON_CTL_EN, 1u, 0u);
|
||
if (!sdrv_ckgen_wait(core_mon_ctrl, CKGEN_CORE_MON_CTL_EN_STA,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
/* clear freq mon */
|
||
RMWREG32(core_mon_ctrl, CKGEN_CORE_MON_CTL_FREQ_LSB, 16u, 0u);
|
||
RMWREG32(core_mon_ctrl, CKGEN_CORE_MON_CTL_FREQ_UPD, 1u, 0u);
|
||
|
||
/* enable core slice debug */
|
||
RMWREG32(core_ctrl, CKGEN_CORE_CTL_DBG_EN, 1u, 1u);
|
||
|
||
/* enable core mon */
|
||
RMWREG32(core_mon_ctrl, CKGEN_CORE_MON_CTL_EN, 1u, 1u);
|
||
if (!sdrv_ckgen_wait(core_mon_ctrl, CKGEN_CORE_MON_CTL_EN_STA,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
goto core_mon_get_rate_out;
|
||
}
|
||
|
||
if (!sdrv_ckgen_wait(core_mon_ctrl, CKGEN_CORE_MON_CTL_FREQ_UPD,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
goto core_mon_get_rate_out;
|
||
}
|
||
|
||
core_mon_ctrl_val = readl(core_mon_ctrl);
|
||
freq_mon = (core_mon_ctrl_val >> CKGEN_CORE_MON_CTL_FREQ_LSB) & CKGEN_CORE_MON_CTL_FREQ_MASK;
|
||
div_a_b = (core_mon_ctrl_val >> CKGEN_CORE_MON_CTL_SRC_SEL) & 0x1;
|
||
|
||
rate = sdrv_ckgen_mon_calc_freq(base, freq_mon, div_a_b);
|
||
|
||
core_mon_get_rate_out:
|
||
|
||
/* disable core mon */
|
||
RMWREG32(core_mon_ctrl, CKGEN_CORE_MON_CTL_EN, 1u, 0u);
|
||
sdrv_ckgen_wait(core_mon_ctrl, CKGEN_CORE_MON_CTL_EN_STA,
|
||
0u, CKGEN_WAIT_TIME);
|
||
|
||
/* disable core slice debug */
|
||
RMWREG32(core_ctrl, CKGEN_CORE_CTL_DBG_EN, 1u, 0u);
|
||
|
||
return rate;
|
||
}
|
||
|
||
void sdrv_ckgen_core_mon_set_thrd(uint32_t base, uint32_t id,
|
||
uint16_t low_thrd, uint16_t high_thrd)
|
||
{
|
||
uint32_t mon_thrd = CKGEN_CORE_MON_THRD_BASE(base, id);
|
||
RMWREG32(mon_thrd, CKGEN_CORE_MON_THRD_LOW_LSB, 16u, low_thrd);
|
||
RMWREG32(mon_thrd, CKGEN_CORE_MON_THRD_HIGH_LSB, 16u, high_thrd);
|
||
}
|
||
|
||
bool sdrv_ckgen_mon_xcg_is_gated(uint32_t base, uint8_t cg_type, uint32_t id)
|
||
{
|
||
uint32_t state;
|
||
|
||
sdrv_ckgen_xcg_amon_enable(base, cg_type, id, true);
|
||
|
||
state = sdrv_ckgen_xcg_get_amon_state(base, cg_type, id);
|
||
|
||
sdrv_ckgen_xcg_amon_enable(base, cg_type, id, false);
|
||
|
||
return state ? false : true;
|
||
}
|
||
|
||
bool sdrv_ckgen_mon_pll_is_gated(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t state;
|
||
|
||
sdrv_ckgen_pll_mon_enable(base, id, 0xffff);
|
||
|
||
state = sdrv_ckgen_pll_mon_get_state(base, id);
|
||
|
||
sdrv_ckgen_pll_mon_disable(base, id);
|
||
|
||
return state ? false : true;
|
||
}
|
||
|
||
bool sdrv_ckgen_mon_xtal_is_gated(uint32_t base)
|
||
{
|
||
uint32_t state;
|
||
|
||
sdrv_ckgen_xtal_mon_enable(base, 0xffff);
|
||
|
||
state = sdrv_ckgen_xtal_mon_get_xtal_state(base);
|
||
|
||
sdrv_ckgen_xtal_mon_disable(base);
|
||
|
||
return state ? false : true;
|
||
}
|
||
|
||
uint32_t sdrv_ckgen_dbg_mon_get_ip_rate(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t ip_ctrl = CKGEN_IP_CTL_BASE(base, id);
|
||
uint32_t rate;
|
||
|
||
/* enable ip slice debug */
|
||
RMWREG32(ip_ctrl, CKGEN_IP_CTL_DBG_EN, 1u, 1u);
|
||
|
||
rate = sdrv_ckgen_dbg_mon_get_rate(base, 0, id);
|
||
|
||
/* disable ip slice debug */
|
||
RMWREG32(ip_ctrl, CKGEN_IP_CTL_DBG_EN, 1u, 0u);
|
||
|
||
return rate;
|
||
}
|
||
|
||
uint32_t sdrv_ckgen_dbg_mon_get_bus_rate(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t bus_ctrl = CKGEN_BUS_CTL_BASE(base, id);
|
||
uint32_t rate;
|
||
|
||
/* enable bus slice debug */
|
||
RMWREG32(bus_ctrl, CKGEN_BUS_CTL_DBG_EN, 1u, 1u);
|
||
|
||
rate = sdrv_ckgen_dbg_mon_get_rate(base, 1, id);
|
||
|
||
/* disable bus slice debug */
|
||
RMWREG32(bus_ctrl, CKGEN_BUS_CTL_DBG_EN, 1u, 0u);
|
||
|
||
return rate;
|
||
}
|
||
|
||
uint32_t sdrv_ckgen_dbg_mon_get_core_rate(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t core_ctrl = CKGEN_CORE_CTL_BASE(base, id);
|
||
uint32_t rate;
|
||
|
||
/* enable core slice debug */
|
||
RMWREG32(core_ctrl, CKGEN_CORE_CTL_DBG_EN, 1u, 1u);
|
||
|
||
rate = sdrv_ckgen_dbg_mon_get_rate(base, 2, id);
|
||
|
||
/* disable core slice debug */
|
||
RMWREG32(core_ctrl, CKGEN_CORE_CTL_DBG_EN, 1u, 0u);
|
||
|
||
return rate;
|
||
}
|
||
|
||
uint32_t sdrv_ckgen_dbg_mon_get_ext_rate(uint32_t base, uint32_t id)
|
||
{
|
||
return sdrv_ckgen_dbg_mon_get_rate(base, 3, id);
|
||
}
|
||
|
||
void sdrv_ckgen_dbg_mon_ip_select(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t ip_ctrl = CKGEN_IP_CTL_BASE(base, id);
|
||
uint32_t dbg_mon_ctl = base + CKGEN_DBG_MON_CTL;
|
||
|
||
RMWREG32(ip_ctrl, CKGEN_IP_CTL_DBG_EN, 1u, 1u);
|
||
sdrv_ckgen_dbg_mon_src_config(base, 0, id);
|
||
RMWREG32(dbg_mon_ctl, CKGEN_DBG_MON_CTL_DBG_GATING_EN, 1u, 1u);
|
||
}
|
||
|
||
void sdrv_ckgen_dbg_mon_bus_select(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t bus_ctrl = CKGEN_BUS_CTL_BASE(base, id);
|
||
uint32_t dbg_mon_ctl = base + CKGEN_DBG_MON_CTL;
|
||
|
||
RMWREG32(bus_ctrl, CKGEN_BUS_CTL_DBG_EN, 1u, 1u);
|
||
sdrv_ckgen_dbg_mon_src_config(base, 1, id);
|
||
RMWREG32(dbg_mon_ctl, CKGEN_DBG_MON_CTL_DBG_GATING_EN, 1u, 1u);
|
||
}
|
||
|
||
void sdrv_ckgen_dbg_mon_core_select(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t core_ctrl = CKGEN_CORE_CTL_BASE(base, id);
|
||
uint32_t dbg_mon_ctl = base + CKGEN_DBG_MON_CTL;
|
||
|
||
RMWREG32(core_ctrl, CKGEN_CORE_CTL_DBG_EN, 1u, 1u);
|
||
sdrv_ckgen_dbg_mon_src_config(base, 2, id);
|
||
RMWREG32(dbg_mon_ctl, CKGEN_DBG_MON_CTL_DBG_GATING_EN, 1u, 1u);
|
||
}
|
||
|
||
void sdrv_ckgen_dbg_mon_ext_select(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t dbg_mon_ctl = base + CKGEN_DBG_MON_CTL;
|
||
|
||
sdrv_ckgen_dbg_mon_src_config(base, 3, id);
|
||
RMWREG32(dbg_mon_ctl, CKGEN_DBG_MON_CTL_DBG_GATING_EN, 1u, 1u);
|
||
}
|
||
|
||
uint32_t sdrv_ckgen_24M_mon_get_rate(uint32_t base)
|
||
{
|
||
uint32_t low_spd_chk_ctl = base + CKGEN_LOW_SPD_CHK_CTL;
|
||
uint32_t mon_val;
|
||
uint32_t freq_mon;
|
||
uint32_t rate = 0;
|
||
|
||
if (BIT(readl(low_spd_chk_ctl), CKGEN_LOW_SPD_CHK_CTL_MON_EN)) {
|
||
RMWREG32(low_spd_chk_ctl, CKGEN_LOW_SPD_CHK_CTL_MON_EN, 1u, 0u);
|
||
if (!sdrv_ckgen_wait(low_spd_chk_ctl, CKGEN_LOW_SPD_CHK_CTL_MON_EN_STA,
|
||
0u, CKGEN_WAIT_TIME)) {
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
/* set 32k 24m src */
|
||
RMWREG32(low_spd_chk_ctl, CKGEN_LOW_SPD_CHK_CTL_24M_SEL, 6u, 0u);
|
||
RMWREG32(low_spd_chk_ctl, CKGEN_LOW_SPD_CHK_CTL_32K_SEL, 6u, 0u);
|
||
|
||
/* clear freq mon */
|
||
RMWREG32(low_spd_chk_ctl, CKGEN_LOW_SPD_CHK_CTL_FREQ_MON_LSB, 16u, 0u);
|
||
RMWREG32(low_spd_chk_ctl, CKGEN_LOW_SPD_CHK_CTL_MON_UPD, 1u, 0u);
|
||
|
||
/* enable mon */
|
||
RMWREG32(low_spd_chk_ctl, CKGEN_LOW_SPD_CHK_CTL_LOSS_DIS, 1u, 0u);
|
||
RMWREG32(low_spd_chk_ctl, CKGEN_LOW_SPD_CHK_CTL_MON_EN, 1u, 1u);
|
||
if (!sdrv_ckgen_wait(low_spd_chk_ctl, CKGEN_LOW_SPD_CHK_CTL_MON_EN_STA,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
goto mon_24m_rate_out;
|
||
}
|
||
|
||
if (!sdrv_ckgen_wait(low_spd_chk_ctl, CKGEN_LOW_SPD_CHK_CTL_MON_UPD,
|
||
1u, CKGEN_WAIT_TIME)) {
|
||
goto mon_24m_rate_out;
|
||
}
|
||
|
||
mon_val = readl(low_spd_chk_ctl);
|
||
freq_mon = (mon_val >> CKGEN_LOW_SPD_CHK_CTL_FREQ_MON_LSB) & CKGEN_LOW_SPD_CHK_CTL_FREQ_MON_MASK;
|
||
rate = freq_mon * 32000;
|
||
|
||
mon_24m_rate_out:
|
||
|
||
RMWREG32(low_spd_chk_ctl, CKGEN_LOW_SPD_CHK_CTL_MON_EN, 1u, 0u);
|
||
sdrv_ckgen_wait(low_spd_chk_ctl, CKGEN_LOW_SPD_CHK_CTL_MON_EN_STA,
|
||
0u, CKGEN_WAIT_TIME);
|
||
|
||
return rate;
|
||
}
|
||
|
||
void sdrv_ckgen_cqm_enable(uint32_t base, uint32_t id,
|
||
uint16_t duty, uint16_t jitter)
|
||
{
|
||
uint32_t dbg_mon_ctl = base + CKGEN_DBG_MON_CTL;
|
||
uint32_t cqm_ctl = CKGEN_CQM_CTL_BASE(base, id);
|
||
|
||
/* enable cqm gating */
|
||
RMWREG32(dbg_mon_ctl, CKGEN_DBG_MON_CTL_CQM_GATING_EN, 1u, 1u);
|
||
|
||
/* config cqm jitter and duty */
|
||
RMWREG32(cqm_ctl, CKGEN_CQM_CTL_JITTER_RATE_LSB, 6u, jitter);
|
||
RMWREG32(cqm_ctl, CKGEN_CQM_CTL_DUTY_RATE_LSB, 6u, duty);
|
||
|
||
/* enable cqm mon */
|
||
RMWREG32(cqm_ctl, CKGEN_CQM_CTL_MON_EN, 1u, 1u);
|
||
}
|
||
|
||
void sdrv_ckgen_cqm_disable(uint32_t base, uint32_t id)
|
||
{
|
||
uint32_t dbg_mon_ctl = base + CKGEN_DBG_MON_CTL;
|
||
uint32_t cqm_ctl = CKGEN_CQM_CTL_BASE(base, id);
|
||
|
||
RMWREG32(cqm_ctl, CKGEN_CQM_CTL_MON_EN, 1u, 0u);
|
||
RMWREG32(dbg_mon_ctl, CKGEN_DBG_MON_CTL_CQM_GATING_EN, 1u, 0u);
|
||
}
|
||
|
||
void sdrv_ckgen_cqm_cor_int_enable(uint32_t base, uint32_t id, bool en)
|
||
{
|
||
RMWREG32(base + CKGEN_CQM_COR_EN, (id % 7u), 1u, en);
|
||
}
|
||
|
||
void sdrv_ckgen_cqm_unc_int_enable(uint32_t base, uint32_t id, bool en)
|
||
{
|
||
RMWREG32(base + CKGEN_CQM_UNC_EN, (id % 7u), 1u, en);
|
||
}
|
||
|
||
bool sdrv_ckgen_cqm_get_duty_int_state(uint32_t base, uint32_t id)
|
||
{
|
||
return !!(readl(base + CKGEN_CQM_DUTY_INT_STA) >> (id % 7u));
|
||
}
|
||
|
||
bool sdrv_ckgen_cqm_get_jitter_int_state(uint32_t base, uint32_t id)
|
||
{
|
||
return !!(readl(base + CKGEN_CQM_JITTER_INT_STA) >> (id % 7u));
|
||
}
|
||
|
||
void sdrv_ckgen_cqm_clear_duty_int_state(uint32_t base, uint32_t id)
|
||
{
|
||
RMWREG32(base + CKGEN_CQM_DUTY_INT_STA, (id % 7u), 1u, 0u);
|
||
}
|
||
|
||
void sdrv_ckgen_cqm_clear_jitter_int_state(uint32_t base, uint32_t id)
|
||
{
|
||
RMWREG32(base + CKGEN_CQM_JITTER_INT_STA, (id % 7u), 1u, 0u);
|
||
}
|