Skip to content

Commit cbde747

Browse files
finley1226wzyy2
authored andcommitted
MINIARM: 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 294770d commit cbde747

1 file changed

Lines changed: 101 additions & 8 deletions

File tree

drivers/cpufreq/cpufreq-dt.c

Lines changed: 101 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
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>
@@ -30,6 +31,10 @@
3031
#include <linux/thermal.h>
3132

3233
#define MAX_CLUSTERS 2
34+
#define MAX_PROP_NAME_LEN 6
35+
#define VERSION_ELEMENTS 1
36+
#define INVALID_VALUE 0xff
37+
#define SAFE_FREQ (24 * 67 * 1000000)
3338

3439
struct private_data {
3540
struct device *cpu_dev;
@@ -43,6 +48,8 @@ static struct freq_attr *cpufreq_dt_attr[] = {
4348
NULL,
4449
};
4550

51+
static unsigned char package_info = INVALID_VALUE;
52+
extern unsigned long apll_safefreq;
4653
static int set_target(struct cpufreq_policy *policy, unsigned int index)
4754
{
4855
struct private_data *priv = policy->driver_data;
@@ -51,6 +58,87 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index)
5158
policy->freq_table[index].frequency * 1000);
5259
}
5360

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

143231
regulator_put(cpu_reg);
232+
233+
ret = fetch_package_info(cpu_dev, &package_info);
234+
if (ret)
235+
dev_dbg(cpu_dev, "Failed to fetch wafer_info\n");
236+
144237
return 0;
145238
}
146239

@@ -151,9 +244,8 @@ static int cpufreq_init(struct cpufreq_policy *policy)
151244
struct device *cpu_dev;
152245
struct clk *cpu_clk;
153246
struct dev_pm_opp *suspend_opp;
154-
#ifdef CONFIG_ARCH_ROCKCHIP
155247
struct cpumask cpus;
156-
#endif
248+
157249
unsigned int transition_latency;
158250
unsigned long cur_freq;
159251
bool opp_v1 = false;
@@ -187,6 +279,12 @@ static int cpufreq_init(struct cpufreq_policy *policy)
187279
goto out_put_clk;
188280
}
189281

282+
if (!opp_v1) {
283+
ret = set_opp_info(cpu_dev);
284+
if (ret)
285+
dev_err(cpu_dev, "Failed to set_opp_info: %d\n", ret);
286+
}
287+
190288
/*
191289
* OPP layer will be taking care of regulators now, but it needs to know
192290
* the name of the regulator first.
@@ -211,7 +309,6 @@ static int cpufreq_init(struct cpufreq_policy *policy)
211309
*
212310
* OPPs might be populated at runtime, don't check for error here
213311
*/
214-
#ifdef CONFIG_ARCH_ROCKCHIP
215312
ret = dev_pm_opp_of_add_table(cpu_dev);
216313
if (ret) {
217314
dev_err(cpu_dev, "couldn't find opp table for cpu:%d, %d\n",
@@ -224,9 +321,6 @@ static int cpufreq_init(struct cpufreq_policy *policy)
224321
dev_pm_opp_of_remove_table(cpu_dev);
225322
}
226323
}
227-
#else
228-
dev_pm_opp_of_cpumask_add_table(policy->cpus);
229-
#endif
230324

231325
/*
232326
* But we need OPP table to function so if it is not there let's
@@ -329,12 +423,11 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
329423
struct cpumask cpus;
330424
struct private_data *priv = policy->driver_data;
331425

332-
#ifdef CONFIG_ARCH_ROCKCHIP
333426
cpumask_set_cpu(policy->cpu, policy->cpus);
334427
if (cpufreq_generic_suspend(policy))
335428
pr_err("%s: Failed to suspend driver: %p\n", __func__, policy);
336429
cpumask_clear_cpu(policy->cpu, policy->cpus);
337-
#endif
430+
338431
priv->cpu_dev = get_cpu_device(policy->cpu);
339432
cpufreq_cooling_unregister(priv->cdev);
340433
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);

0 commit comments

Comments
 (0)