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>
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
3439struct 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 ;
4653static 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