RDK Documentation (Open Sourced RDK Components)
therm_mon.c
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2016 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * 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,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 
20 
21 
22 /**
23 * @defgroup iarmmgrs
24 * @{
25 * @defgroup power
26 * @{
27 **/
28 
29 
30 #ifdef __cplusplus
31 extern "C"
32 {
33 #endif
34 #ifdef ENABLE_THERMAL_PROTECTION
35 #include <sys/stat.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 
39 #include "mfr_temperature.h"
40 #include "plat_power.h"
41 #include "pwrlogger.h"
42 
43 
44 int uint32_compare( const void* a, const void* b)
45 {
46  const uint32_t l = * ((const uint32_t*) a);
47  const uint32_t r = * ((const uint32_t*) b);
48 
49  if ( l == r ) return 0;
50  else if ( l < r ) return -1;
51  else return 1;
52 }
53 
54 
55 int PLAT_API_DetemineClockSpeeds(uint32_t *cpu_rate_Normal, uint32_t *cpu_rate_Scaled, uint32_t *cpu_rate_Minimal)
56 {
57  FILE * fp;
58  uint32_t normal = 0;
59  uint32_t scaled = 0;
60  uint32_t minimal = 0;
61  uint32_t freqList[32];
62  uint32_t numFreqs = 0;
63  uint32_t i;
64 
65  fp = fopen ("/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies", "r");
66  if (fp == 0) {
67  LOG("[%s:%d] Unable to open '/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies' for reading\n", __FUNCTION__, __LINE__);
68  return 0;
69  }
70 
71  /* Determine available frequencies */
72  while (numFreqs < sizeof(freqList)/sizeof(freqList[0]) && (fscanf(fp, "%u", &freqList[numFreqs]) == 1))
73  numFreqs++;
74 
75  if (numFreqs<=0) {
76  LOG("[%s] **ERROR** Unable to read sacaling frequencies!\n", __FUNCTION__);
77  fclose(fp); //CID:158617 - Resource leak
78  return -1;
79  }
80 
81  /* Ensure frequencies are sorted */
82  qsort( (void*)freqList, numFreqs, sizeof(freqList[0]), uint32_compare );
83  LOG("[%s] Scaling Frequency List:\n", __FUNCTION__);
84  for(i=0; i < numFreqs; i++) LOG (" [%s] %uhz\n", __FUNCTION__, freqList[i]);
85 
86  /* Select normal, scaled and minimal from the list */
87  minimal=freqList[0];
88  scaled=freqList[numFreqs/2];
89  normal=freqList[numFreqs-1];
90  LOG("[%s] Using -- Normal:%u Scaled:%u Minimal:%u\n", __FUNCTION__, normal, scaled, minimal);
91 
92  fclose(fp);
93 
94  if (cpu_rate_Normal) *cpu_rate_Normal = normal;
95  if (cpu_rate_Scaled) *cpu_rate_Scaled = scaled;
96  if (cpu_rate_Minimal) *cpu_rate_Minimal = minimal;
97  return 1;
98 }
99 
100 int PLAT_API_SetClockSpeed(uint32_t speed)
101 {
102  FILE* fp = NULL;
103  uint32_t cur_speed = 0;
104  LOG("[%s]Setting clock speed to [%d]\n", __FUNCTION__, speed );
105  //Opening the clock speed adjusting
106 
107  fp = fopen ("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "w");
108  if (fp == 0) {
109  LOG("[%s:%d] Unable to open '/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor' for writing\n", __FUNCTION__, __LINE__);
110  return 0;
111  }
112 
113  /* Switch to 'userspace' mode */
114  fprintf(fp, "userspace");
115  fclose(fp);
116 
117  fp = fopen ("/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed", "w");
118  if (fp == 0) {
119  LOG("[%s:%d] Unable to open '/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed' for writing\n", __FUNCTION__, __LINE__);
120  return 0;
121  }
122 
123  /* Set the desired speed */
124  fprintf(fp, "%u", speed);
125  fclose(fp);
126 
127  if (PLAT_API_GetClockSpeed(&cur_speed) != 1 ) {
128  LOG("[%s:%d] Failed to read current CPU speed\n", __FUNCTION__, __LINE__);
129  return 1;
130  }
131 
132  LOG("[%s] Clock speed set to [%d]\n", __FUNCTION__, cur_speed );
133 
134  return (speed == cur_speed) ? 1 : 0;
135 }
136 
137 int PLAT_API_GetClockSpeed(uint32_t *speed)
138 {
139  FILE* fp = NULL;
140 
141 #ifdef ENABLE_LLAMA_PLATCO
142  fp = fopen ("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq", "r");
143  if (fp == 0) {
144  LOG("[%s:%d] Unable to open '/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq' for writing\n", __FUNCTION__, __LINE__);
145  return 0;
146  }
147 #else
148  fp = fopen ("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq", "r");
149  if (fp == 0) {
150  LOG("[%s:%d] Unable to open '/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq' for writing\n", __FUNCTION__, __LINE__);
151  return 0;
152  }
153 #endif
154 
155  if(0 >= fscanf(fp, "%u", speed)) {
156  LOG("[%s:%d] Unable to get the speed \n", __FUNCTION__, __LINE__);
157  }
158  fclose(fp); //CID:103784 - checked return
159 
160  return 1;
161 }
162 
163 int PLAT_API_GetTemperature(IARM_Bus_PWRMgr_ThermalState_t *curState, float *curTemperature, float *wifiTemperature)
164 {
165  mfrTemperatureState_t state;
166  int temperatureValue;
167  int wifiTempValue;
168  int retValue = 0;
169 
170  mfrError_t result = mfrGetTemperature(&state, &temperatureValue, &wifiTempValue);
171 
172 #if 0
173  /* Leave this debug code here commented out (or otherwise disabled by default). This is used in testing to allow manually controlling the returned temperature.
174  This helps test functionallity without actually haveing to heat up the box */
175  {
176  FILE *fp;
177  state = (mfrTemperatureState_t)IARM_BUS_PWRMGR_TEMPERATURE_NORMAL;
178  temperatureValue=50.0;
179  wifiTempValue=50.0;
180  result = mfrERR_NONE;
181 
182  fp = fopen ("/opt/force_temp.soc", "r");
183  if (fp) {
184  fscanf(fp, "%d", &temperatureValue);
185  fclose(fp);
186  }
187 
188  fp = fopen ("/opt/force_temp.wifi", "r");
189  if (fp) {
190  fscanf(fp, "%d", &wifiTempValue);
191  fclose(fp);
192  }
193 
194  fp = fopen ("/opt/force_temp.state", "r");
195  if (fp) {
196  fscanf(fp, "%d", &state);
197  fclose(fp);
198  }
199  }
200 #endif
201 
202  if (result == mfrERR_NONE)
203  {
204  LOG("[%s] Got MFR Temperatures SoC:%d Wifi:%d\n", __FUNCTION__, temperatureValue, wifiTempValue);
205  *curState = (IARM_Bus_PWRMgr_ThermalState_t )state;
206  *curTemperature = temperatureValue;
207  *wifiTemperature = wifiTempValue;
208  retValue = 1;
209  }
210 
211  return retValue;
212 }
213 
214 int PLAT_API_SetTempThresholds(float tempHigh, float tempCritical)
215 {
216  mfrError_t response = mfrSetTempThresholds(tempHigh,tempCritical);
217  int result = (response == mfrERR_NONE) ?1:0;
218 
219  return result;
220 }
221 
222 int PLAT_API_GetTempThresholds(float *tempHigh, float *tempCritical)
223 {
224  int result = 0;
225  int highTemp = 0, criticalTemp= 0;
226 
227  mfrError_t response = mfrGetTempThresholds(&highTemp, &criticalTemp);
228  if(mfrERR_NONE == response)
229  {
230  result = 1;
231  *tempHigh = highTemp;
232  *tempCritical = criticalTemp;
233  }
234 
235  return result;
236 }
237 #endif //ENABLE_THERMAL_PROTECTION
238 #ifdef __cplusplus
239 }
240 #endif
241 
242 
243 /** @} */
244 /** @} */
mfrGetTempThresholds
mfrError_t mfrGetTempThresholds(int *tempHigh, int *tempCritical)
Get the temperature thresholds which determine the state returned ​​* from a call to mfrGetTemperatur...
IARM_Bus_PWRMgr_ThermalState_t
enum _IARM_Bus_PWRMgr_ThermalState_t IARM_Bus_PWRMgr_ThermalState_t
Enumerator which represents the possible temeperature states.
mfrGetTemperature
mfrError_t mfrGetTemperature(mfrTemperatureState_t *state, int *temperatureValue, int *wifiTemp)
get current temperature of the core
mfrSetTempThresholds
mfrError_t mfrSetTempThresholds(int tempHigh, int tempCritical)
Set temperature thresholds which will determine the state returned ​​* from a call to mfrGetTemperatu...