增加所有文件
This commit is contained in:
396
drivers/source/clk/sdrv_ckgen_dump.c
Normal file
396
drivers/source/clk/sdrv_ckgen_dump.c
Normal file
@@ -0,0 +1,396 @@
|
||||
/**
|
||||
* @file sdrv_ckgen_dump.c
|
||||
* @brief semidrive ckgen dump source file.
|
||||
*
|
||||
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#if CONFIG_CLK_DUMP
|
||||
|
||||
#include <sdrv_ckgen.h>
|
||||
#include <compiler.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <debug.h>
|
||||
#include <bits.h>
|
||||
#include <regs_base.h>
|
||||
#include "sdrv_ckgen_common.h"
|
||||
#include "sdrv_ckgen_dump.h"
|
||||
#include "sdrv_ckgen_hw_access.h"
|
||||
#include "sdrv_pll_hw_access.h"
|
||||
#include "sdrv_fs24m_hw_access.h"
|
||||
#include "sdrv_fs32k_hw_access.h"
|
||||
|
||||
static struct list_node g_root_clk;
|
||||
static sdrv_ckgen_clk_t g_ckgen_clk;
|
||||
|
||||
static sdrv_clk_t **sdrv_ckgen_get_store_info(sdrv_ckgen_node_t *node, uint32_t *size)
|
||||
{
|
||||
sdrv_clk_t **store_list = NULL;
|
||||
uint32_t list_num = 0;
|
||||
|
||||
switch (node->type) {
|
||||
case CKGEN_RC24M_TYPE:
|
||||
case CKGEN_FS24M_TYPE:
|
||||
case CKGEN_RC32K_TYPE:
|
||||
case CKGEN_FS32K_TYPE:
|
||||
store_list = &g_ckgen_clk.ref_clk[0];
|
||||
list_num = SDRV_CKGEN_REF_MAX_NUM;
|
||||
break;
|
||||
|
||||
case CKGEN_PLL_CTRL_TYPE:
|
||||
store_list = &g_ckgen_clk.pll_ctrl[0];
|
||||
list_num = SDRV_CKGEN_PLL_CTRL_MAX_NUM;
|
||||
break;
|
||||
|
||||
case CKGEN_PLL_LVDS_TYPE:
|
||||
store_list = &g_ckgen_clk.pll_lvds[0];
|
||||
list_num = SDRV_CKGEN_PLL_LVDS_MAX_NUM;
|
||||
break;
|
||||
|
||||
case CKGEN_SF_BUS_SLICE_TYPE:
|
||||
store_list = &g_ckgen_clk.sf_bus[0];
|
||||
list_num = SDRV_CKGEN_SF_BUS_MAX_NUM;
|
||||
break;
|
||||
|
||||
case CKGEN_BUS_SLICE_TYPE:
|
||||
store_list = &g_ckgen_clk.bus[0];
|
||||
list_num = SDRV_CKGEN_BUS_MAX_NUM;
|
||||
break;
|
||||
|
||||
case CKGEN_CORE_SLICE_TYPE:
|
||||
store_list = &g_ckgen_clk.core[0];
|
||||
list_num = SDRV_CKGEN_CORE_MAX_NUM;
|
||||
break;
|
||||
|
||||
case CKGEN_IP_SLICE_TYPE:
|
||||
if (node->base == APB_CKGEN_SF_BASE) {
|
||||
store_list = &g_ckgen_clk.saf_ip[0];
|
||||
list_num = SDRV_CKGEN_SAF_IP_MAX_NUM;
|
||||
}
|
||||
else {
|
||||
store_list = &g_ckgen_clk.ap_ip[0];
|
||||
list_num = SDRV_CKGEN_AP_IP_MAX_NUM;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
*size = list_num;
|
||||
return store_list;
|
||||
}
|
||||
|
||||
static status_t sdrv_ckgen_add_clknode_global(sdrv_clk_t *clk)
|
||||
{
|
||||
sdrv_clk_t **store_list;
|
||||
uint32_t list_num;
|
||||
|
||||
store_list = sdrv_ckgen_get_store_info((sdrv_ckgen_node_t *)clk->ckgen_ref, &list_num);
|
||||
|
||||
if ((store_list) && (clk->ckgen_ref->id < list_num) && (!store_list[clk->ckgen_ref->id])) {
|
||||
store_list[clk->ckgen_ref->id] = clk;
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
else {
|
||||
return SDRV_CKGEN_CONSTRUCT_CLKTREE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static sdrv_clk_t *sdrv_ckgen_get_clknode_from_global(sdrv_ckgen_node_t *node)
|
||||
{
|
||||
sdrv_clk_t **store_list;
|
||||
uint32_t list_num;
|
||||
|
||||
store_list = sdrv_ckgen_get_store_info(node, &list_num);
|
||||
|
||||
if ((store_list) && (node->id < list_num) && (store_list[node->id])) {
|
||||
return store_list[node->id];
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static sdrv_ckgen_node_t *sdrv_ckgen_get_mux_from_register(sdrv_ckgen_slice_node_t *slice)
|
||||
{
|
||||
uint8_t mux = -1;
|
||||
|
||||
if (slice->clk_node.type == CKGEN_IP_SLICE_TYPE) {
|
||||
mux = sdrv_ckgen_ip_slice_get_mux(slice->clk_node.base, slice->clk_node.id);
|
||||
}
|
||||
else if (slice->clk_node.type == CKGEN_CORE_SLICE_TYPE) {
|
||||
mux = sdrv_ckgen_core_slice_get_mux(slice->clk_node.base, slice->clk_node.id);
|
||||
}
|
||||
else if (slice->clk_node.type == CKGEN_SF_BUS_SLICE_TYPE ||
|
||||
slice->clk_node.type == CKGEN_BUS_SLICE_TYPE) {
|
||||
mux = sdrv_ckgen_bus_slice_get_pre_mux(slice->clk_node.base, slice->clk_node.id);
|
||||
}
|
||||
|
||||
if (mux < slice->parents_num) {
|
||||
return (sdrv_ckgen_node_t *)(slice->parents[mux]);
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static sdrv_ckgen_node_t *sdrv_ckgen_get_parent_ckgen_node(sdrv_ckgen_node_t *node)
|
||||
{
|
||||
sdrv_ckgen_node_t *ret = NULL;
|
||||
sdrv_ckgen_slice_node_t *slice;
|
||||
sdrv_pll_node_t *pll;
|
||||
|
||||
switch (node->type) {
|
||||
case CKGEN_PLL_CTRL_TYPE:
|
||||
case CKGEN_PLL_LVDS_TYPE:
|
||||
pll = (sdrv_pll_node_t *)node;
|
||||
ret = (sdrv_ckgen_node_t *)(pll->parent);
|
||||
break;
|
||||
|
||||
case CKGEN_SF_BUS_SLICE_TYPE:
|
||||
case CKGEN_BUS_SLICE_TYPE:
|
||||
case CKGEN_CORE_SLICE_TYPE:
|
||||
case CKGEN_IP_SLICE_TYPE:
|
||||
slice = (sdrv_ckgen_slice_node_t *)node;
|
||||
ret = sdrv_ckgen_get_mux_from_register(slice);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sdrv_ckgen_fs_source_check(sdrv_clk_t *clk)
|
||||
{
|
||||
uint32_t src;
|
||||
|
||||
if (clk->ckgen_ref->type == CKGEN_FS24M_TYPE) {
|
||||
src = sdrv_fs24m_fs_sel_get(clk->ckgen_ref->base);
|
||||
if (src == FS24M_FS_SEL_XTAL) {
|
||||
clk->name = "fs24m(xtal)";
|
||||
}
|
||||
else {
|
||||
clk->name = "fs24m(rc)";
|
||||
}
|
||||
}
|
||||
else {
|
||||
RTC_SS_ACCESS_START();
|
||||
src = sdrv_fs32k_fs_sel_get(clk->ckgen_ref->base);
|
||||
RTC_SS_ACCESS_END();
|
||||
if (src == FS32K_FS_SEL_XTAL) {
|
||||
clk->name = "fs32k(xtal)";
|
||||
}
|
||||
else {
|
||||
clk->name = "fs32k(rc)";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t sdrv_ckgen_node_get_rate(sdrv_ckgen_node_t *node)
|
||||
{
|
||||
uint32_t rate = 0;
|
||||
|
||||
switch (node->type) {
|
||||
case CKGEN_RC24M_TYPE:
|
||||
case CKGEN_FS24M_TYPE:
|
||||
rate = 24000000;
|
||||
break;
|
||||
|
||||
case CKGEN_RC32K_TYPE:
|
||||
case CKGEN_FS32K_TYPE:
|
||||
rate = 32768;
|
||||
break;
|
||||
|
||||
case CKGEN_PLL_CTRL_TYPE:
|
||||
case CKGEN_PLL_LVDS_TYPE:
|
||||
rate = sdrv_pll_get_rate(node);
|
||||
break;
|
||||
|
||||
case CKGEN_SF_BUS_SLICE_TYPE:
|
||||
rate = sdrv_ckgen_bus_mon_get_rate(node->base, node->id, 0);
|
||||
if (rate == 0) {
|
||||
rate = sdrv_ckgen_bus_get_rate(node, CKGEN_BUS_CLK_OUT_M);
|
||||
}
|
||||
break;
|
||||
|
||||
case CKGEN_BUS_SLICE_TYPE:
|
||||
rate = sdrv_ckgen_bus_mon_get_rate(node->base, node->id, 1);
|
||||
if (rate == 0) {
|
||||
rate = sdrv_ckgen_bus_get_rate(node, CKGEN_BUS_CLK_OUT_N);
|
||||
}
|
||||
break;
|
||||
|
||||
case CKGEN_CORE_SLICE_TYPE:
|
||||
rate = sdrv_ckgen_core_mon_get_rate(node->base, node->id);
|
||||
if (rate == 0) {
|
||||
rate = sdrv_ckgen_get_rate(node);
|
||||
}
|
||||
break;
|
||||
|
||||
case CKGEN_IP_SLICE_TYPE:
|
||||
rate = sdrv_ckgen_ip_mon_get_rate(node->base, node->id);
|
||||
if (rate == 0) {
|
||||
rate = sdrv_ckgen_get_rate(node);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static int calculate_maxdepths(sdrv_clk_t *clk, int depth)
|
||||
{
|
||||
int maxdepths = depth;
|
||||
int namedepth;
|
||||
int tmp;
|
||||
|
||||
if (!clk) {
|
||||
sdrv_clk_t *child = NULL;
|
||||
|
||||
if (list_is_empty(&g_root_clk)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_for_every_entry(&g_root_clk, child, sdrv_clk_t, node) {
|
||||
tmp = calculate_maxdepths(child, depth);
|
||||
if (tmp > maxdepths) {
|
||||
maxdepths = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return maxdepths;
|
||||
}
|
||||
|
||||
namedepth = strlen(clk->name) / 8 + 1;
|
||||
maxdepths = namedepth + depth;
|
||||
|
||||
if (!list_is_empty(&clk->child)) {
|
||||
sdrv_clk_t *child = NULL;
|
||||
|
||||
list_for_every_entry(&clk->child, child, sdrv_clk_t, node) {
|
||||
tmp = calculate_maxdepths(child, depth + 1);
|
||||
if (tmp > maxdepths) {
|
||||
maxdepths = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return maxdepths;
|
||||
}
|
||||
|
||||
static void print_prefix(int depth, const char *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < depth; i++) {
|
||||
ssdk_printf(0, "%s", s);
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_clktree_internal(sdrv_clk_t *clk, int depth, const int maxdepth)
|
||||
{
|
||||
int slice_gate;
|
||||
|
||||
if (!clk) {
|
||||
sdrv_clk_t *child = NULL;
|
||||
|
||||
if (list_is_empty(&g_root_clk)) {
|
||||
return;
|
||||
}
|
||||
|
||||
list_for_every_entry(&g_root_clk, child, sdrv_clk_t, node) {
|
||||
dump_clktree_internal(child, depth, maxdepth);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
print_prefix(depth, "\t");
|
||||
ssdk_printf(0, "%s", clk->name);
|
||||
|
||||
if ((maxdepth - depth) > (int)strlen(clk->name) / 8) {
|
||||
print_prefix(maxdepth - depth - strlen(clk->name) / 8, "\t");
|
||||
}
|
||||
|
||||
slice_gate = sdrv_ckgen_slice_gated((sdrv_ckgen_node_t *)clk->ckgen_ref);
|
||||
|
||||
ssdk_printf(0, "%-15u%s\r\n", sdrv_ckgen_node_get_rate((sdrv_ckgen_node_t *)clk->ckgen_ref),
|
||||
(slice_gate >= 0) ? (slice_gate ? "Gated" : "Active") : "");
|
||||
|
||||
if (!list_is_empty(&clk->child)) {
|
||||
sdrv_clk_t *child = NULL;
|
||||
|
||||
list_for_every_entry(&clk->child, child, sdrv_clk_t, node) {
|
||||
dump_clktree_internal(child, depth + 1, maxdepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status_t sdrv_ckgen_construct_clktree(sdrv_clk_t *clk_nodes, uint32_t node_num)
|
||||
{
|
||||
sdrv_ckgen_node_t *parent;
|
||||
sdrv_clk_t *parent_clk;
|
||||
sdrv_clk_t *clk;
|
||||
status_t ret;
|
||||
|
||||
list_initialize(&g_root_clk);
|
||||
memset(&g_ckgen_clk, 0x0, sizeof(sdrv_ckgen_clk_t));
|
||||
|
||||
for (uint32_t i = 0; i < node_num; i++) {
|
||||
clk = &clk_nodes[i];
|
||||
|
||||
ret = sdrv_ckgen_add_clknode_global(clk);
|
||||
if (ret != SDRV_STATUS_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
list_clear_node(&clk->node);
|
||||
list_initialize(&clk->child);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < node_num; i++) {
|
||||
clk = &clk_nodes[i];
|
||||
|
||||
parent = sdrv_ckgen_get_parent_ckgen_node((sdrv_ckgen_node_t *)clk->ckgen_ref);
|
||||
if (parent) {
|
||||
parent_clk = sdrv_ckgen_get_clknode_from_global(parent);
|
||||
if (parent_clk) {
|
||||
list_add_tail(&parent_clk->child, &clk->node);
|
||||
}
|
||||
else {
|
||||
return SDRV_CKGEN_PARENT_NODE_NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
list_add_tail(&g_root_clk, &clk->node);
|
||||
|
||||
if (clk->ckgen_ref->type == CKGEN_FS24M_TYPE ||
|
||||
clk->ckgen_ref->type == CKGEN_FS32K_TYPE) {
|
||||
sdrv_ckgen_fs_source_check(clk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
status_t sdrv_ckgen_dump_clktree(sdrv_clk_t *clk_node)
|
||||
{
|
||||
int maxdepths;
|
||||
|
||||
maxdepths = calculate_maxdepths(clk_node, 0);
|
||||
dump_clktree_internal(clk_node, 0, maxdepths);
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user