Skip to content

Commit 326a4bb

Browse files
finley1226yihsin-hung
authored andcommitted
cpufreq: dt: rk3288: allow to enable OPPs based on chip version.
Change-Id: I1982248a45b49c17f0e71453f616572bdc6cb257 Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
1 parent cf6f1c1 commit 326a4bb

2 files changed

Lines changed: 102 additions & 18 deletions

File tree

drivers/base/power/opp/core.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -958,12 +958,6 @@ static void _remove_opp_table(struct opp_table *opp_table)
958958
if (!list_empty(&opp_table->opp_list))
959959
return;
960960

961-
if (opp_table->supported_hw)
962-
return;
963-
964-
if (opp_table->prop_name)
965-
return;
966-
967961
if (!IS_ERR(opp_table->regulator))
968962
return;
969963

drivers/cpufreq/cpufreq-dt.c

Lines changed: 102 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,19 @@
2222
#include <linux/cpumask.h>
2323
#include <linux/err.h>
2424
#include <linux/module.h>
25+
#include <linux/nvmem-consumer.h>
2526
#include <linux/of.h>
2627
#include <linux/pm_opp.h>
2728
#include <linux/platform_device.h>
2829
#include <linux/regulator/consumer.h>
2930
#include <linux/slab.h>
3031
#include <linux/thermal.h>
3132

33+
#define MAX_PROP_NAME_LEN 6
34+
#define VERSION_ELEMENTS 1
35+
#define INVALID_VALUE 0xff
36+
#define SAFE_FREQ (24 * 67 * 1000000)
37+
3238
struct private_data {
3339
struct device *cpu_dev;
3440
struct thermal_cooling_device *cdev;
@@ -41,6 +47,8 @@ static struct freq_attr *cpufreq_dt_attr[] = {
4147
NULL,
4248
};
4349

50+
static unsigned char package_info = INVALID_VALUE;
51+
extern unsigned long apll_safefreq;
4452
static int set_target(struct cpufreq_policy *policy, unsigned int index)
4553
{
4654
struct private_data *priv = policy->driver_data;
@@ -49,6 +57,87 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index)
4957
policy->freq_table[index].frequency * 1000);
5058
}
5159

60+
static int fetch_package_info(struct device *dev, unsigned char *package_info)
61+
{
62+
struct nvmem_cell *cell;
63+
unsigned char *buf;
64+
size_t len;
65+
66+
cell = nvmem_cell_get(dev, "package_info");
67+
if (IS_ERR(cell))
68+
return PTR_ERR(cell);
69+
70+
buf = (unsigned char *)nvmem_cell_read(cell, &len);
71+
72+
nvmem_cell_put(cell);
73+
74+
if (IS_ERR(buf))
75+
return PTR_ERR(buf);
76+
77+
if (buf[0] == INVALID_VALUE)
78+
return -EINVAL;
79+
80+
*package_info = buf[0];
81+
kfree(buf);
82+
83+
return 0;
84+
}
85+
86+
static int set_opp_info(struct device *dev)
87+
{
88+
struct device_node *opp_np, *np;
89+
unsigned char chip_vesion;
90+
char name[MAX_PROP_NAME_LEN];
91+
unsigned int version;
92+
unsigned int count = 0;
93+
int ret;
94+
95+
if (package_info == INVALID_VALUE) {
96+
dev_info(dev, "package_info NULL\n");
97+
return 0;
98+
}
99+
100+
opp_np = of_parse_phandle(dev->of_node, "operating-points-v2", 0);
101+
if (!opp_np)
102+
return 0;
103+
for_each_available_child_of_node(opp_np, np) {
104+
ret = of_property_read_u32_index(np, "opp-supported-hw",
105+
VERSION_ELEMENTS - 1,
106+
&version);
107+
if (!ret) {
108+
count++;
109+
break;
110+
}
111+
}
112+
if (count == 0)
113+
return 0;
114+
115+
if ((package_info & 0xc0) == 0xc0) {
116+
chip_vesion = 1;
117+
apll_safefreq = ULONG_MAX;
118+
} else {
119+
chip_vesion = 0;
120+
apll_safefreq = SAFE_FREQ;
121+
}
122+
snprintf(name, MAX_PROP_NAME_LEN, "v%d", chip_vesion);
123+
ret = dev_pm_opp_set_prop_name(dev, name);
124+
if (ret) {
125+
dev_err(dev, "Failed to set prop name\n");
126+
return ret;
127+
}
128+
129+
version = BIT(chip_vesion);
130+
ret = dev_pm_opp_set_supported_hw(dev, &version, VERSION_ELEMENTS);
131+
if (ret) {
132+
dev_err(dev, "Failed to set supported hardware\n");
133+
return ret;
134+
}
135+
136+
dev_info(dev, "chip_version: %d 0x%x\n", chip_vesion, version);
137+
138+
return 0;
139+
}
140+
52141
/*
53142
* An earlier version of opp-v1 bindings used to name the regulator
54143
* "cpu0-supply", we still need to handle that for backwards compatibility.
@@ -139,6 +228,11 @@ static int resources_available(void)
139228
}
140229

141230
regulator_put(cpu_reg);
231+
232+
ret = fetch_package_info(cpu_dev, &package_info);
233+
if (ret)
234+
dev_dbg(cpu_dev, "Failed to fetch wafer_info\n");
235+
142236
return 0;
143237
}
144238

@@ -149,9 +243,8 @@ static int cpufreq_init(struct cpufreq_policy *policy)
149243
struct device *cpu_dev;
150244
struct clk *cpu_clk;
151245
struct dev_pm_opp *suspend_opp;
152-
#ifdef CONFIG_ARCH_ROCKCHIP
153246
struct cpumask cpus;
154-
#endif
247+
155248
unsigned int transition_latency;
156249
bool opp_v1 = false;
157250
const char *name;
@@ -183,6 +276,12 @@ static int cpufreq_init(struct cpufreq_policy *policy)
183276
goto out_put_clk;
184277
}
185278

279+
if (!opp_v1) {
280+
ret = set_opp_info(cpu_dev);
281+
if (ret)
282+
dev_err(cpu_dev, "Failed to set_opp_info: %d\n", ret);
283+
}
284+
186285
/*
187286
* OPP layer will be taking care of regulators now, but it needs to know
188287
* the name of the regulator first.
@@ -207,7 +306,6 @@ static int cpufreq_init(struct cpufreq_policy *policy)
207306
*
208307
* OPPs might be populated at runtime, don't check for error here
209308
*/
210-
#ifdef CONFIG_ARCH_ROCKCHIP
211309
ret = dev_pm_opp_of_add_table(cpu_dev);
212310
if (ret) {
213311
dev_err(cpu_dev, "couldn't find opp table for cpu:%d, %d\n",
@@ -220,9 +318,6 @@ static int cpufreq_init(struct cpufreq_policy *policy)
220318
dev_pm_opp_of_remove_table(cpu_dev);
221319
}
222320
}
223-
#else
224-
dev_pm_opp_of_cpumask_add_table(policy->cpus);
225-
#endif
226321

227322
/*
228323
* But we need OPP table to function so if it is not there let's
@@ -318,12 +413,11 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
318413
struct cpumask cpus;
319414
struct private_data *priv = policy->driver_data;
320415

321-
#ifdef CONFIG_ARCH_ROCKCHIP
322416
cpumask_set_cpu(policy->cpu, policy->cpus);
323417
if (cpufreq_generic_suspend(policy))
324418
pr_err("%s: Failed to suspend driver: %p\n", __func__, policy);
325419
cpumask_clear_cpu(policy->cpu, policy->cpus);
326-
#endif
420+
327421
priv->cpu_dev = get_cpu_device(policy->cpu);
328422
cpufreq_cooling_unregister(priv->cdev);
329423
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
@@ -373,11 +467,7 @@ static void cpufreq_ready(struct cpufreq_policy *policy)
373467
}
374468

375469
static struct cpufreq_driver dt_cpufreq_driver = {
376-
#ifdef CONFIG_ARCH_ROCKCHIP
377470
.flags = CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY,
378-
#else
379-
.flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
380-
#endif
381471
.verify = cpufreq_generic_frequency_table_verify,
382472
.target_index = set_target,
383473
.get = cpufreq_generic_get,

0 commit comments

Comments
 (0)