sdk-hwV1.3/lichee/linux-4.9/drivers/clk/sunxi/clk-sdm.c

100 lines
2.6 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2022 Allwinner.
* Emma <liujuan1@allwinnertech.com>
*/
#include "clk-sdm.h"
#include <dt-bindings/clock/sunxi-clk.h>
struct clk_sdm_info *sdm_info;
static int len;
int sunxi_parse_sdm_info(struct device_node *node)
{
int i = 0;
struct device_node *child_node = NULL;
struct device_node *sdm_node = NULL;
if (!node)
return -1;
sdm_node = of_get_child_by_name(node, "sdm_info");
if (!sdm_node)
return -1;
len = of_get_child_count(sdm_node);
if (!len)
return -1;
sdm_info = kcalloc(len, sizeof(struct clk_sdm_info), GFP_KERNEL);
if (!sdm_info) {
return -ENOMEM;
}
for_each_child_of_node(sdm_node, child_node) {
if (of_property_read_u32(child_node, "sdm-enable", &sdm_info[i].sdm_enable))
continue;
if (sdm_info[i].sdm_enable != DTS_SDM_OFF &&
sdm_info[i].sdm_enable != DTS_SDM_ON) {
pr_err("clk: %s invaild enable: %d, should be 0 or 1\n",
child_node->name, sdm_info[i].sdm_enable);
continue;
}
if (of_property_read_u32(child_node, "sdm-factor", &sdm_info[i].sdm_factor))
continue;
/* the unit of factor is 1/1000 */
if (sdm_info[i].sdm_factor > 99) {
pr_err("clk: %s invaild factor: %d, should be within 99\n",
child_node->name, sdm_info[i].sdm_factor);
continue;
}
if (of_property_read_u32(child_node, "freq-mode", &sdm_info[i].freq_mode)) {
sdm_info[i].freq_mode = TR_N;
} else {
if (sdm_info[i].freq_mode < 0 || sdm_info[i].freq_mode > 1) {
pr_err("clk: %s invaild freq_mod: %d, should be within 0~1, use default TR_N\n",
child_node->name, sdm_info[i].sdm_factor);
sdm_info[i].freq_mode = TR_N;
}
}
if (of_property_read_u32(child_node, "sdm-freq", &sdm_info[i].sdm_freq)) {
sdm_info[i].sdm_freq = FREQ_31_5;
} else {
if (sdm_info[i].sdm_freq < 0 || sdm_info[i].sdm_freq > 3) {
pr_err("clk: %s invaild sdm_freq : %d, should be within 0~3, use default FREQ_31_5\n", child_node->name, sdm_info[i].sdm_factor);
sdm_info[i].sdm_freq = FREQ_31_5;
}
}
sdm_info[i].clk_name = child_node->name;
i++;
}
len = i;
return 0;
}
EXPORT_SYMBOL_GPL(sunxi_parse_sdm_info);
int sunxi_clk_get_sdm_info(const char *clk_name, struct clk_sdm_info *sdm_info_out)
{
int i;
sdm_info_out->clk_name = clk_name;
if (!sdm_info)
return -1;
for (i = 0; i < len; i++) {
if (!strcmp(clk_name, sdm_info[i].clk_name)) {
sdm_info_out->sdm_enable = sdm_info[i].sdm_enable;
sdm_info_out->sdm_factor = sdm_info[i].sdm_factor;
sdm_info_out->freq_mode = sdm_info[i].freq_mode;
sdm_info_out->sdm_freq = sdm_info[i].sdm_freq;
return 0;
};
}
return -1;
}
EXPORT_SYMBOL_GPL(sunxi_clk_get_sdm_info);