From 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 10 May 2024 07:44:59 +0000
Subject: [PATCH] gmac get mac form eeprom
---
kernel/drivers/soc/rockchip/rockchip_opp_select.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 202 insertions(+), 26 deletions(-)
diff --git a/kernel/drivers/soc/rockchip/rockchip_opp_select.c b/kernel/drivers/soc/rockchip/rockchip_opp_select.c
index 8caae5c..6c496ad 100644
--- a/kernel/drivers/soc/rockchip/rockchip_opp_select.c
+++ b/kernel/drivers/soc/rockchip/rockchip_opp_select.c
@@ -12,6 +12,7 @@
#include <linux/nvmem-consumer.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
+#include <linux/rockchip/rockchip_sip.h>
#include <linux/slab.h>
#include <linux/soc/rockchip/pvtm.h>
#include <linux/thermal.h>
@@ -1004,15 +1005,15 @@
}
if (of_property_read_u32(np, "rockchip,pvtpll-len-min-rate", &min_rate))
- return;
+ goto out;
if (of_property_read_u32(np, "rockchip,pvtpll-len-max-rate", &max_rate))
- return;
+ goto out;
if (of_property_read_u32(np, "rockchip,pvtpll-len-margin", &margin))
- return;
+ goto out;
opp_table = dev_pm_opp_get_opp_table(info->dev);
if (!opp_table)
- return;
+ goto out;
old_rate = clk_get_rate(opp_table->clk);
opp_flag = OPP_ADD_LENGTH | ((margin & OPP_LENGTH_MASK) << OPP_LENGTH_SHIFT);
@@ -1033,8 +1034,97 @@
clk_set_rate(opp_table->clk, old_rate);
dev_pm_opp_put_opp_table(opp_table);
+out:
+ of_node_put(np);
}
EXPORT_SYMBOL(rockchip_pvtpll_add_length);
+
+void rockchip_init_pvtpll_table(struct rockchip_opp_info *info, int bin)
+{
+ struct device_node *np = NULL;
+ struct property *prop = NULL;
+ struct of_phandle_args clkspec = { 0 };
+ struct arm_smccc_res res;
+ char prop_name[NAME_MAX];
+ u32 *value;
+ int count;
+ int ret, i;
+
+ if (!info)
+ return;
+
+ np = of_parse_phandle(info->dev->of_node, "operating-points-v2", 0);
+ if (!np) {
+ dev_warn(info->dev, "OPP-v2 not supported\n");
+ return;
+ }
+
+ ret = of_parse_phandle_with_args(info->dev->of_node, "clocks",
+ "#clock-cells", 0, &clkspec);
+ if (ret)
+ goto out;
+ info->pvtpll_clk_id = clkspec.args[0];
+ of_node_put(clkspec.np);
+
+ res = sip_smc_get_pvtpll_info(PVTPLL_GET_INFO, info->pvtpll_clk_id);
+ if (res.a0)
+ goto out;
+ if (!res.a1)
+ info->pvtpll_low_temp = true;
+
+ if (bin > 0) {
+ snprintf(prop_name, sizeof(prop_name),
+ "rockchip,pvtpll-table-B%d", bin);
+ prop = of_find_property(np, prop_name, NULL);
+ }
+ if (!prop)
+ sprintf(prop_name, "rockchip,pvtpll-table");
+
+ prop = of_find_property(np, prop_name, NULL);
+ if (!prop)
+ goto out;
+
+ count = of_property_count_u32_elems(np, prop_name);
+ if (count < 0) {
+ dev_err(info->dev, "%s: Invalid %s property (%d)\n",
+ __func__, prop_name, count);
+ goto out;
+ } else if (count % 5) {
+ dev_err(info->dev, "Invalid count of %s\n", prop_name);
+ goto out;
+ }
+
+ value = kmalloc_array(count, sizeof(*value), GFP_KERNEL);
+ if (!value)
+ goto out;
+ ret = of_property_read_u32_array(np, prop_name, value, count);
+ if (ret) {
+ dev_err(info->dev, "%s: error parsing %s: %d\n",
+ __func__, prop_name, ret);
+ goto free_value;
+ }
+
+ for (i = 0; i < count; i += 5) {
+ res = sip_smc_pvtpll_config(PVTPLL_ADJUST_TABLE,
+ info->pvtpll_clk_id, value[i],
+ value[i + 1], value[i + 2],
+ value[i + 3], value[i + 4]);
+ if (res.a0) {
+ dev_err(info->dev,
+ "%s: error cfg clk_id=%u %u %u %u %u %u (%d)\n",
+ __func__, info->pvtpll_clk_id, value[i],
+ value[i + 1], value[i + 2], value[i + 3],
+ value[i + 4], (int)res.a0);
+ goto free_value;
+ }
+ }
+
+free_value:
+ kfree(value);
+out:
+ of_node_put(np);
+}
+EXPORT_SYMBOL(rockchip_init_pvtpll_table);
static int rockchip_get_pvtm_pvtpll(struct device *dev, struct device_node *np,
char *reg_name)
@@ -1186,10 +1276,15 @@
snprintf(name, sizeof(name),
"rockchip,p%d-pvtm-voltage-sel", process);
prop = of_find_property(np, name, NULL);
- } else if (bin >= 0) {
+ } else if (bin > 0) {
of_property_read_u32(np, "rockchip,pvtm-hw", &hw);
if (hw && (hw & BIT(bin))) {
sprintf(name, "rockchip,pvtm-voltage-sel-hw");
+ prop = of_find_property(np, name, NULL);
+ }
+ if (!prop) {
+ snprintf(name, sizeof(name),
+ "rockchip,pvtm-voltage-sel-B%d", bin);
prop = of_find_property(np, name, NULL);
}
}
@@ -1633,6 +1728,10 @@
rockchip_adjust_opp_by_irdrop(dev, np, &safe_rate, &max_rate);
dev_info(dev, "avs=%d\n", avs);
+
+ if (!safe_rate && !scale)
+ goto out_np;
+
clk = of_clk_get_by_name(np, NULL);
if (IS_ERR(clk)) {
if (!safe_rate)
@@ -1646,14 +1745,14 @@
if (safe_rate)
irdrop_scale = rockchip_pll_clk_rate_to_scale(clk, safe_rate);
- if (max_rate)
- opp_scale = rockchip_pll_clk_rate_to_scale(clk, max_rate);
target_scale = max(irdrop_scale, scale);
if (target_scale <= 0)
goto out_clk;
dev_dbg(dev, "target_scale=%d, irdrop_scale=%d, scale=%d\n",
target_scale, irdrop_scale, scale);
+ if (max_rate)
+ opp_scale = rockchip_pll_clk_rate_to_scale(clk, max_rate);
if (avs == AVS_SCALING_RATE) {
ret = rockchip_pll_clk_adaptive_scaling(clk, target_scale);
if (ret)
@@ -1838,13 +1937,78 @@
}
EXPORT_SYMBOL(rockchip_set_intermediate_rate);
+static int rockchip_get_opp_clk(struct device *dev, struct device_node *np,
+ struct rockchip_opp_info *info)
+{
+ struct clk_bulk_data *clks;
+ struct of_phandle_args clkspec;
+ int ret = 0, num_clks = 0, i;
+
+ if (of_find_property(np, "rockchip,opp-clocks", NULL)) {
+ num_clks = of_count_phandle_with_args(np, "rockchip,opp-clocks",
+ "#clock-cells");
+ if (num_clks <= 0)
+ return 0;
+ clks = devm_kcalloc(dev, num_clks, sizeof(*clks), GFP_KERNEL);
+ if (!clks)
+ return -ENOMEM;
+ for (i = 0; i < num_clks; i++) {
+ ret = of_parse_phandle_with_args(np,
+ "rockchip,opp-clocks",
+ "#clock-cells", i,
+ &clkspec);
+ if (ret < 0) {
+ dev_err(dev, "%s: failed to parse opp clk %d\n",
+ np->name, i);
+ goto error;
+ }
+ clks[i].clk = of_clk_get_from_provider(&clkspec);
+ of_node_put(clkspec.np);
+ if (IS_ERR(clks[i].clk)) {
+ ret = PTR_ERR(clks[i].clk);
+ clks[i].clk = NULL;
+ dev_err(dev, "%s: failed to get opp clk %d\n",
+ np->name, i);
+ goto error;
+ }
+ }
+ } else {
+ num_clks = of_clk_get_parent_count(np);
+ if (num_clks <= 0)
+ return 0;
+ clks = devm_kcalloc(dev, num_clks, sizeof(*clks), GFP_KERNEL);
+ if (!clks)
+ return -ENOMEM;
+ for (i = 0; i < num_clks; i++) {
+ clks[i].clk = of_clk_get(np, i);
+ if (IS_ERR(clks[i].clk)) {
+ ret = PTR_ERR(clks[i].clk);
+ clks[i].clk = NULL;
+ dev_err(dev, "%s: failed to get clk %d\n",
+ np->name, i);
+ goto error;
+ }
+ }
+ }
+ info->clks = clks;
+ info->num_clks = num_clks;
+
+ return 0;
+error:
+ while (--i >= 0)
+ clk_put(clks[i].clk);
+ devm_kfree(dev, clks);
+
+ return ret;
+}
+
int rockchip_init_opp_table(struct device *dev, struct rockchip_opp_info *info,
char *lkg_name, char *reg_name)
{
struct device_node *np;
int bin = -EINVAL, process = -EINVAL;
int scale = 0, volt_sel = -EINVAL;
- int ret = 0, num_clks = 0, i;
+ int ret = 0;
u32 freq;
/* Get OPP descriptor node */
@@ -1857,24 +2021,10 @@
goto next;
info->dev = dev;
- num_clks = of_clk_get_parent_count(np);
- if (num_clks > 0) {
- info->clks = devm_kcalloc(dev, num_clks, sizeof(*info->clks),
- GFP_KERNEL);
- if (!info->clks) {
- ret = -ENOMEM;
- goto out;
- }
- for (i = 0; i < num_clks; i++) {
- info->clks[i].clk = of_clk_get(np, i);
- if (IS_ERR(info->clks[i].clk)) {
- ret = PTR_ERR(info->clks[i].clk);
- dev_err(dev, "%s: failed to get clk %d\n",
- np->name, i);
- goto out;
- }
- }
- info->num_clks = num_clks;
+ ret = rockchip_get_opp_clk(dev, np, info);
+ if (ret)
+ goto out;
+ if (info->clks) {
ret = clk_bulk_prepare_enable(info->num_clks, info->clks);
if (ret) {
dev_err(dev, "failed to enable opp clks\n");
@@ -1900,6 +2050,7 @@
next:
rockchip_get_soc_info(dev, np, &bin, &process);
+ rockchip_init_pvtpll_table(info, bin);
rockchip_get_scale_volt_sel(dev, lkg_name, reg_name, bin, process,
&scale, &volt_sel);
if (info && info->data && info->data->set_soc_info)
@@ -1925,6 +2076,31 @@
}
EXPORT_SYMBOL(rockchip_init_opp_table);
+void rockchip_uninit_opp_table(struct device *dev, struct rockchip_opp_info *info)
+{
+ struct opp_table *opp_table;
+
+ if (info) {
+ kfree(info->opp_table);
+ info->opp_table = NULL;
+ devm_kfree(dev, info->clks);
+ info->clks = NULL;
+ devm_kfree(dev, info->volt_rm_tbl);
+ info->volt_rm_tbl = NULL;
+ }
+
+ opp_table = dev_pm_opp_get_opp_table(dev);
+ if (IS_ERR(opp_table))
+ return;
+ dev_pm_opp_of_remove_table(dev);
+ if (opp_table->prop_name)
+ dev_pm_opp_put_prop_name(opp_table);
+ if (opp_table->supported_hw)
+ dev_pm_opp_put_supported_hw(opp_table);
+ dev_pm_opp_put_opp_table(opp_table);
+}
+EXPORT_SYMBOL(rockchip_uninit_opp_table);
+
MODULE_DESCRIPTION("ROCKCHIP OPP Select");
MODULE_AUTHOR("Finley Xiao <finley.xiao@rock-chips.com>, Liang Chen <cl@rock-chips.com>");
MODULE_LICENSE("GPL");
--
Gitblit v1.6.2