Skip to content

Commit 2f285a0

Browse files
JianyuWang0623xiaoxiang781216
authored andcommitted
Thermal: Support cpufreq cooling device
Signed-off-by: wangjianyu3 <[email protected]>
1 parent 338b5d7 commit 2f285a0

File tree

5 files changed

+257
-0
lines changed

5 files changed

+257
-0
lines changed

drivers/thermal/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,11 @@ config THERMAL_GOVERNOR_STEP_WISE
2323
---help---
2424
Enable step wise governor.
2525

26+
config THERMAL_CDEV_CPUFREQ
27+
bool "Thermal cpufreq cooling device"
28+
default n
29+
depends on CPUFREQ
30+
---help---
31+
Enable thermal cpufreq cooling device.
32+
2633
endif # THERMAL

drivers/thermal/Make.defs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ ifeq ($(CONFIG_THERMAL_GOVERNOR_STEP_WISE),y)
2828
CSRCS += thermal_step_wise.c
2929
endif
3030

31+
ifeq ($(CONFIG_THERMAL_CDEV_CPUFREQ),y)
32+
CSRCS += thermal_cpufreq_cooling.c
33+
endif
34+
3135
DEPPATH += --dep-path thermal
3236
VPATH += thermal
3337

drivers/thermal/thermal_core.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -848,5 +848,12 @@ int thermal_init(void)
848848
}
849849
#endif
850850

851+
#ifdef CONFIG_THERMAL_CDEV_CPUFREQ
852+
if (NULL == thermal_cpufreq_cooling_register())
853+
{
854+
return -ENOTSUP;
855+
}
856+
#endif
857+
851858
return ret;
852859
}

drivers/thermal/thermal_core.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ struct thermal_instance_s
5757

5858
void
5959
thermal_cooling_device_update (FAR struct thermal_cooling_device_s *cdev);
60+
#ifdef CONFIG_THERMAL_CDEV_CPUFREQ
61+
FAR struct thermal_cooling_device_s *thermal_cpufreq_cooling_register(void);
62+
void thermal_cpufreq_cooling_unregister(
63+
FAR struct thermal_cooling_device_s *cdev);
64+
#endif /* CONFIG_THERMAL_CDEV_CPUFREQ */
6065

6166
/* Zone Device */
6267

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
/****************************************************************************
2+
* drivers/thermal/thermal_cpufreq_cooling.c
3+
*
4+
* Licensed to the Apache Software Foundation (ASF) under one or more
5+
* contributor license agreements. See the NOTICE file distributed with
6+
* this work for additional information regarding copyright ownership. The
7+
* ASF licenses this file to you under the Apache License, Version 2.0 (the
8+
* "License"); you may not use this file except in compliance with the
9+
* License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16+
* License for the specific language governing permissions and limitations
17+
* under the License.
18+
*
19+
****************************************************************************/
20+
21+
/****************************************************************************
22+
* Included Files
23+
****************************************************************************/
24+
25+
#include <nuttx/cpufreq.h>
26+
#include <nuttx/kmalloc.h>
27+
28+
#include "thermal_core.h"
29+
30+
/****************************************************************************
31+
* Private Types
32+
****************************************************************************/
33+
34+
struct cpufreq_cooling_device_s
35+
{
36+
FAR const struct cpufreq_frequency_table *table;
37+
FAR struct cpufreq_policy *policy;
38+
FAR struct cpufreq_qos *qos;
39+
unsigned int cur_state;
40+
unsigned int max_state;
41+
};
42+
43+
/****************************************************************************
44+
* Private Function Prototypes
45+
****************************************************************************/
46+
47+
static int cpufreq_get_max_state(FAR struct thermal_cooling_device_s *cdev,
48+
FAR unsigned int *state);
49+
static int cpufreq_get_state (FAR struct thermal_cooling_device_s *cdev,
50+
FAR unsigned int *state);
51+
static int cpufreq_set_state (FAR struct thermal_cooling_device_s *cdev,
52+
unsigned int state);
53+
54+
/****************************************************************************
55+
* Private Data
56+
****************************************************************************/
57+
58+
static const struct thermal_cooling_device_ops_s g_cpufreq_cdev_ops =
59+
{
60+
.set_state = cpufreq_set_state,
61+
.get_state = cpufreq_get_state,
62+
.get_max_state = cpufreq_get_max_state,
63+
};
64+
65+
/****************************************************************************
66+
* Private Functions
67+
****************************************************************************/
68+
69+
static int cpufreq_get_max_state(FAR struct thermal_cooling_device_s *cdev,
70+
FAR unsigned int *state)
71+
{
72+
struct cpufreq_cooling_device_s *cpufreq_cdev = cdev->devdata;
73+
74+
*state = cpufreq_cdev->max_state;
75+
return OK;
76+
}
77+
78+
static int cpufreq_get_state(FAR struct thermal_cooling_device_s *cdev,
79+
FAR unsigned int *state)
80+
{
81+
struct cpufreq_cooling_device_s *cpufreq_cdev = cdev->devdata;
82+
83+
*state = cpufreq_cdev->cur_state;
84+
return OK;
85+
}
86+
87+
static int cpufreq_set_state(FAR struct thermal_cooling_device_s *cdev,
88+
unsigned int state)
89+
{
90+
struct cpufreq_cooling_device_s *cpufreq_cdev = cdev->devdata;
91+
unsigned int index = cpufreq_cdev->max_state - state;
92+
int ret;
93+
94+
thinfo("CPU Freq cooling %u %u \n",
95+
cpufreq_cdev->table[index].frequency,
96+
cpufreq_cdev->table[index + 1].frequency);
97+
98+
if (cpufreq_cdev->qos == NULL)
99+
{
100+
cpufreq_cdev->qos = cpufreq_qos_add_request(
101+
cpufreq_cdev->policy,
102+
cpufreq_cdev->table[index].frequency,
103+
cpufreq_cdev->table[index + 1].frequency);
104+
if (!cpufreq_cdev->qos)
105+
{
106+
therr("Add qos request failed!");
107+
return -EINVAL;
108+
}
109+
}
110+
else
111+
{
112+
ret = cpufreq_qos_update_request(
113+
cpufreq_cdev->qos,
114+
cpufreq_cdev->table[index].frequency,
115+
cpufreq_cdev->table[index + 1].frequency);
116+
if (ret < 0)
117+
{
118+
therr("Update qos request failed!");
119+
return ret;
120+
}
121+
}
122+
123+
cpufreq_cdev->cur_state = state;
124+
return OK;
125+
}
126+
127+
/****************************************************************************
128+
* Public Functions
129+
****************************************************************************/
130+
131+
/****************************************************************************
132+
* Name: thermal_cpufreq_cooling_register
133+
*
134+
* Description:
135+
* Register cpufreq cooling device
136+
*
137+
* Input Parameters:
138+
* policy - cpufreq policy
139+
*
140+
* Returned Value:
141+
* Addr of created cooling device entry
142+
****************************************************************************/
143+
144+
FAR struct thermal_cooling_device_s *thermal_cpufreq_cooling_register(void)
145+
{
146+
FAR struct cpufreq_cooling_device_s *cpufreq_cdev;
147+
FAR const struct cpufreq_frequency_table *table;
148+
FAR struct thermal_cooling_device_s *cdev;
149+
FAR struct cpufreq_driver **driver;
150+
FAR struct cpufreq_policy *policy;
151+
unsigned int count;
152+
153+
policy = cpufreq_policy_get();
154+
if (policy == NULL)
155+
{
156+
therr("Get cpufreq policy failed!\n");
157+
return NULL;
158+
}
159+
160+
driver = (FAR struct cpufreq_driver **)policy;
161+
162+
table = (*driver)->get_table(policy);
163+
if (table == NULL)
164+
{
165+
therr("Get cpufreq table failed!\n");
166+
return NULL;
167+
}
168+
169+
for (count = 0; table[count].frequency != CPUFREQ_TABLE_END; count++)
170+
{
171+
}
172+
173+
if (count < 2)
174+
{
175+
therr("Invalid cpufreq table!\n");
176+
return NULL;
177+
}
178+
179+
cpufreq_cdev = kmm_zalloc(sizeof(*cpufreq_cdev));
180+
if (cpufreq_cdev == NULL)
181+
{
182+
therr("No memory for cpufreq cooling device registering!\n");
183+
return NULL;
184+
}
185+
186+
cpufreq_cdev->table = table;
187+
cpufreq_cdev->policy = policy;
188+
cpufreq_cdev->max_state = count - 2;
189+
thinfo("max level of cpufreq is %d \n", cpufreq_cdev->max_state);
190+
191+
cdev = thermal_cooling_device_register("cpufreq", cpufreq_cdev,
192+
&g_cpufreq_cdev_ops);
193+
if (cdev == NULL)
194+
{
195+
kmm_free(cpufreq_cdev);
196+
}
197+
198+
return cdev;
199+
}
200+
201+
/****************************************************************************
202+
* Name: thermal_cpufreq_cooling_unregister
203+
*
204+
* Description:
205+
* Unregister cpufreq cooling device
206+
*
207+
* Input Parameters:
208+
* cdev - Addr of cpufre cooling devcie entry
209+
*
210+
* Returned Value:
211+
* None
212+
****************************************************************************/
213+
214+
void
215+
thermal_cpufreq_cooling_unregister(FAR struct thermal_cooling_device_s *cdev)
216+
{
217+
struct cpufreq_cooling_device_s *cpufreq_cdev;
218+
int ret;
219+
220+
cpufreq_cdev = cdev->devdata;
221+
222+
if (cpufreq_cdev->qos)
223+
{
224+
ret = cpufreq_qos_remove_request(cpufreq_cdev->qos);
225+
if (ret < 0)
226+
{
227+
thinfo("ret=%d\n", ret);
228+
therr("Remove cpufreq qos failed!\n");
229+
}
230+
}
231+
232+
thermal_cooling_device_unregister(cdev);
233+
kmm_free(cpufreq_cdev);
234+
}

0 commit comments

Comments
 (0)