mtk_cooler_3Gmutt.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. #include <linux/version.h>
  2. #include <linux/kernel.h>
  3. #include <linux/module.h>
  4. #include <linux/types.h>
  5. #include <linux/kobject.h>
  6. #include <linux/proc_fs.h>
  7. #include <asm/uaccess.h>
  8. #include <linux/err.h>
  9. #include <linux/syscalls.h>
  10. #include "mt-plat/mtk_thermal_monitor.h"
  11. static int cl_debug_flag;
  12. #define mtk_cooler_3Gmutt_dprintk_always(fmt, args...)pr_notice("[thermal/cooler/3Gmutt]" fmt, ##args)
  13. #define mtk_cooler_3Gmutt_dprintk(fmt, args...) \
  14. do { \
  15. if (1 == cl_mutt_klog_on) \
  16. pr_debug("[thermal/cooler/3Gmutt]" fmt, ##args); \
  17. } while (0)
  18. #define MAX_NUM_INSTANCE_MTK_COOLER_3GMUTT 4
  19. #define MTK_CL_3GMUTT_GET_LIMIT(limit, state) \
  20. { (limit) = (short) (((unsigned long) (state))>>16); }
  21. #define MTK_CL_3GMUTT_SET_LIMIT(limit, state) \
  22. { state = ((((unsigned long) (state))&0xFFFF) | ((short) limit<<16)); }
  23. #define MTK_CL_3GMUTT_GET_CURR_STATE(curr_state, state) \
  24. { curr_state = (((unsigned long) (state))&0xFFFF); }
  25. #define MTK_CL_3GMUTT_SET_CURR_STATE(curr_state, state) \
  26. do { \
  27. if (0 == curr_state) \
  28. state &= ~0x1; \
  29. else \
  30. state |= 0x1; \
  31. } while (0)
  32. static kuid_t uid = KUIDT_INIT(0);
  33. static kgid_t gid = KGIDT_INIT(1000);
  34. static int cl_mutt_klog_on;
  35. static struct thermal_cooling_device *cl_mutt_dev[MAX_NUM_INSTANCE_MTK_COOLER_3GMUTT] = { 0 };
  36. static unsigned int cl_mutt_param[MAX_NUM_INSTANCE_MTK_COOLER_3GMUTT] = { 0 };
  37. static unsigned long cl_mutt_state[MAX_NUM_INSTANCE_MTK_COOLER_3GMUTT] = { 0 };
  38. static unsigned int cl_mutt_cur_limit;
  39. static unsigned long last_md_boot_cnt;
  40. static unsigned int tm_pid;
  41. static unsigned int tm_input_pid_3Gtest;
  42. static struct task_struct g_task;
  43. static struct task_struct *pg_task = &g_task;
  44. #define MAX_LEN 256
  45. /* unsigned int tm_input_pid_3Gtest= 0; */
  46. int mddulthro_pid_read(struct seq_file *m, void *v)
  47. {
  48. /* int ret; */
  49. /* char tmp[MAX_LEN] = {0}; */
  50. seq_printf(m, "%d\n", tm_input_pid_3Gtest);
  51. /* ret = strlen(tmp); */
  52. /* memcpy(buf, tmp, ret*sizeof(char)); */
  53. mtk_cooler_3Gmutt_dprintk_always("[%s] %d\n", __func__, tm_input_pid_3Gtest);
  54. return 0;
  55. }
  56. ssize_t mddulthro_pid_write(struct file *file, const char __user *buf, size_t count, loff_t *data)
  57. {
  58. int ret = 0;
  59. char tmp[MAX_LEN] = { 0 };
  60. int len = 0;
  61. /* write data to the buffer */
  62. len = (count < (sizeof(tmp) - 1)) ? count : (sizeof(tmp) - 1);
  63. if (copy_from_user(tmp, buf, len))
  64. return -EFAULT;
  65. ret = kstrtouint(tmp, 10, &tm_input_pid_3Gtest);
  66. if (ret)
  67. WARN_ON(1);
  68. mtk_cooler_3Gmutt_dprintk_always("[%s] %s = %d\n", __func__, tmp, tm_input_pid_3Gtest);
  69. return len;
  70. }
  71. static int mddulthro_pid_open(struct inode *inode, struct file *file)
  72. {
  73. /* return single_open(file, mddulthro_pid_read, NULL); */
  74. return single_open(file, mddulthro_pid_read, PDE_DATA(inode));
  75. }
  76. static const struct file_operations mddulthro_pid_fops = {
  77. .owner = THIS_MODULE,
  78. .open = mddulthro_pid_open,
  79. .read = seq_read,
  80. .llseek = seq_lseek,
  81. .write = mddulthro_pid_write,
  82. .release = single_release,
  83. };
  84. static int mutt3G_send_signal(int level, int level2)
  85. {
  86. int ret = 0;
  87. int thro = level;
  88. int thro2 = level2;
  89. /* g_limit_tput = level; */
  90. mtk_cooler_3Gmutt_dprintk_always("%s +++ ,level=%d,level2=%d\n", __func__, level, level2);
  91. if (tm_input_pid_3Gtest == 0) {
  92. mtk_cooler_3Gmutt_dprintk_always("[%s] pid is empty\n", __func__);
  93. ret = -1;
  94. }
  95. mtk_cooler_3Gmutt_dprintk_always("[%s] pid is %d, %d, %d, %d\n", __func__, tm_pid,
  96. tm_input_pid_3Gtest, thro, thro2);
  97. if (ret == 0 && tm_input_pid_3Gtest != tm_pid) {
  98. tm_pid = tm_input_pid_3Gtest;
  99. pg_task = get_pid_task(find_vpid(tm_pid), PIDTYPE_PID);
  100. mtk_cooler_3Gmutt_dprintk_always("[%s] line %d\n", __func__, __LINE__);
  101. }
  102. if (ret == 0 && pg_task) {
  103. siginfo_t info;
  104. info.si_signo = SIGIO;
  105. info.si_errno = 4;
  106. info.si_code = thro;
  107. info.si_addr = NULL;
  108. ret = send_sig_info(SIGIO, &info, pg_task);
  109. }
  110. if (ret != 0)
  111. mtk_cooler_3Gmutt_dprintk_always("[%s] ret=%d\n", __func__, ret);
  112. return ret;
  113. }
  114. static void mtk_cl_mutt_set_mutt_limit(void)
  115. {
  116. /* TODO: optimize */
  117. int i = 0, ret = 0;
  118. int min_limit = 255;
  119. unsigned int min_param = 0;
  120. unsigned int md_active = 0;
  121. unsigned int md_suspend = 0;
  122. unsigned int md_final = 0;
  123. int limit = 0;
  124. for (; i < MAX_NUM_INSTANCE_MTK_COOLER_3GMUTT; i++) {
  125. unsigned long curr_state;
  126. MTK_CL_3GMUTT_GET_CURR_STATE(curr_state, cl_mutt_state[i]);
  127. mtk_cooler_3Gmutt_dprintk_always("[%s] curr_state = %lu\n", __func__, curr_state);
  128. if (1 == curr_state) {
  129. md_active = (cl_mutt_param[i] & 0x0000FF00) >> 8;
  130. md_suspend = (cl_mutt_param[i] & 0x00FF0000) >> 16;
  131. md_final = (cl_mutt_param[i] & 0x000FFFF0) >> 4;
  132. /* mtk_cooler_3Gmutt_dprintk_always("[%s]i= %d ,active=0x%x,suspend=0x%x\n",
  133. __func__, i,md_active,md_suspend); */
  134. /* a cooler with 0 active or 0 suspend is not allowed */
  135. if (md_active == 0 || md_suspend == 0)
  136. goto err_unreg;
  137. /* compare the active/suspend ratio */
  138. if (md_active >= md_suspend)
  139. limit = md_active / md_suspend;
  140. else
  141. limit = (0 - md_suspend) / md_active;
  142. if (limit <= min_limit) {
  143. min_limit = limit;
  144. min_param = cl_mutt_param[i];
  145. }
  146. } else {
  147. /* mutt3G_send_signal(-1,-1); */
  148. /* mtk_cooler_3Gmutt_dprintk_always("[%s]i= %d ,active=0x%x,suspend=0x%d\n",
  149. __func__, i,md_active,md_suspend); */
  150. }
  151. }
  152. mtk_cooler_3Gmutt_dprintk_always("[%s]i= %d ,min_param=%x,cl_mutt_cur_limit=%x\n", __func__,
  153. i, min_param, cl_mutt_cur_limit);
  154. mtk_cooler_3Gmutt_dprintk_always("[%s]i= %d ,md_final=0x%x,active=0x%x,suspend=0x%x\n",
  155. __func__, i, md_final, md_active, md_suspend);
  156. if (min_param != cl_mutt_cur_limit) {
  157. cl_mutt_cur_limit = min_param;
  158. /* last_md_boot_cnt = ccci_get_md_boot_count(MD_SYS1); */
  159. /* ret = exec_ccci_kern_func_by_md_id(MD_SYS1, ID_THROTTLING_CFG, (char*) &cl_mutt_cur_limit, 4); */
  160. mutt3G_send_signal(md_final, cl_mutt_cur_limit);
  161. mtk_cooler_3Gmutt_dprintk_always("[%s] ret %d param %x bcnt %lul\n", __func__, ret,
  162. cl_mutt_cur_limit, last_md_boot_cnt);
  163. }
  164. err_unreg:
  165. return;
  166. }
  167. static int mtk_cl_mutt_get_max_state(struct thermal_cooling_device *cdev, unsigned long *state)
  168. {
  169. *state = 1;
  170. mtk_cooler_3Gmutt_dprintk("mtk_cl_mutt_get_max_state() %s %lu\n", cdev->type, *state);
  171. return 0;
  172. }
  173. static int mtk_cl_mutt_get_cur_state(struct thermal_cooling_device *cdev, unsigned long *state)
  174. {
  175. MTK_CL_3GMUTT_GET_CURR_STATE(*state, *((unsigned long *)cdev->devdata));
  176. mtk_cooler_3Gmutt_dprintk("mtk_cl_mutt_get_cur_state() %s %lu\n", cdev->type, *state);
  177. return 0;
  178. }
  179. static int mtk_cl_mutt_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
  180. {
  181. mtk_cooler_3Gmutt_dprintk("mtk_cl_mutt_set_cur_state() %s %lu pid=%d\n", cdev->type, state,
  182. tm_input_pid_3Gtest);
  183. MTK_CL_3GMUTT_SET_CURR_STATE(state, *((unsigned long *)cdev->devdata));
  184. mtk_cl_mutt_set_mutt_limit();
  185. return 0;
  186. }
  187. /* bind fan callbacks to fan device */
  188. static struct thermal_cooling_device_ops mtk_cl_mutt_ops = {
  189. .get_max_state = mtk_cl_mutt_get_max_state,
  190. .get_cur_state = mtk_cl_mutt_get_cur_state,
  191. .set_cur_state = mtk_cl_mutt_set_cur_state,
  192. };
  193. static int mtk_cooler_mutt_register_ltf(void)
  194. {
  195. int i;
  196. mtk_cooler_3Gmutt_dprintk("register ltf\n");
  197. for (i = MAX_NUM_INSTANCE_MTK_COOLER_3GMUTT; i-- > 0;) {
  198. char temp[20] = { 0 };
  199. sprintf(temp, "mtk-cl-3gmutt%02d", i);
  200. cl_mutt_dev[i] = mtk_thermal_cooling_device_register(temp,
  201. (void *)&cl_mutt_state[i], /* put mutt state to cooler devdata */
  202. &mtk_cl_mutt_ops);
  203. }
  204. mtk_cooler_3Gmutt_dprintk_always("[%s]i= %d\n", __func__, i);
  205. return 0;
  206. }
  207. static void mtk_cooler_mutt_unregister_ltf(void)
  208. {
  209. int i;
  210. mtk_cooler_3Gmutt_dprintk("unregister ltf\n");
  211. for (i = MAX_NUM_INSTANCE_MTK_COOLER_3GMUTT; i-- > 0;) {
  212. if (cl_mutt_dev[i]) {
  213. mtk_thermal_cooling_device_unregister(cl_mutt_dev[i]);
  214. cl_mutt_dev[i] = NULL;
  215. cl_mutt_state[i] = 0;
  216. }
  217. }
  218. mtk_cooler_3Gmutt_dprintk_always("[%s]i= %d\n", __func__, i);
  219. }
  220. static int _mtk_cl_mutt_proc_read(struct seq_file *m, void *v)
  221. {
  222. /**
  223. * The format to print out:
  224. * kernel_log <0 or 1>
  225. * <mtk-cl-mutt<ID>> <active (ms)> <suspend (ms)> <param> <state>
  226. * ..
  227. */
  228. {
  229. int i = 0;
  230. seq_printf(m, "klog %d\n", cl_mutt_klog_on);
  231. seq_printf(m, "curr_limit %x\n", cl_mutt_cur_limit);
  232. for (; i < MAX_NUM_INSTANCE_MTK_COOLER_3GMUTT; i++) {
  233. unsigned int active;
  234. unsigned int suspend;
  235. unsigned long curr_state;
  236. active = (cl_mutt_param[i] & 0x0000FF00) >> 8;
  237. suspend = (cl_mutt_param[i] & 0x00FF0000) >> 16;
  238. MTK_CL_3GMUTT_GET_CURR_STATE(curr_state, cl_mutt_state[i]);
  239. seq_printf(m, "mtk-cl-3gmutt%02d %u %u %x, state %lu\n", i, active, suspend,
  240. cl_mutt_param[i], curr_state);
  241. }
  242. mtk_cooler_3Gmutt_dprintk_always("[%s]i= %d\n", __func__, i);
  243. }
  244. return 0;
  245. }
  246. static ssize_t _mtk_cl_mutt_proc_write(struct file *filp, const char __user *buffer, size_t count,
  247. loff_t *data)
  248. {
  249. int len = 0;
  250. char desc[128];
  251. int klog_on, mutt0_a, mutt0_s, mutt1_a, mutt1_s, mutt2_a, mutt2_s, mutt3_a, mutt3_s;
  252. len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1);
  253. if (copy_from_user(desc, buffer, len))
  254. return 0;
  255. desc[len] = '\0';
  256. /**
  257. * sscanf format <klog_on> <mtk-cl-mutt00 active (ms)> <mtk-cl-mutt00 suspended (ms)> <mtk-cl-mutt01 active (ms)> <mtk-cl-mutt01 suspended (ms)> <mtk-cl-mutt02 active (ms)> <mtk-cl-mutt02 suspended (ms)>...
  258. * <klog_on> can only be 0 or 1
  259. * <mtk-cl-mutt* active/suspended (ms) > can only be positive integer or 0 to denote no limit
  260. */
  261. if (NULL == data) {
  262. mtk_cooler_3Gmutt_dprintk("[%s] null data\n", __func__);
  263. return -EINVAL;
  264. }
  265. /* WARNING: Modify here if MTK_THERMAL_MONITOR_COOLER_MAX_EXTRA_CONDITIONS is changed to other than 4 */
  266. #if (4 == MAX_NUM_INSTANCE_MTK_COOLER_3GMUTT)
  267. /* cl_mutt_param[0] = 0; */
  268. /* cl_mutt_param[1] = 0; */
  269. /* cl_mutt_param[2] = 0; */
  270. if (1 <= sscanf(desc, "%d %d %d %d %d %d %d %d %d",
  271. &klog_on, &mutt0_a, &mutt0_s, &mutt1_a, &mutt1_s, &mutt2_a, &mutt2_s, &mutt3_a, &mutt3_s)) {
  272. if (klog_on == 0 || klog_on == 1)
  273. cl_mutt_klog_on = klog_on;
  274. if (mutt0_a == 0)
  275. cl_mutt_param[0] = 0;
  276. else if (mutt0_a >= 100 && mutt0_a <= 25500 && mutt0_s >= 100 && mutt0_s <= 25500)
  277. cl_mutt_param[0] = ((mutt0_s / 100) << 16) | ((mutt0_a / 100) << 8) | 1;
  278. if (mutt1_a == 0)
  279. cl_mutt_param[1] = 0;
  280. else if (mutt1_a >= 100 && mutt1_a <= 25500 && mutt1_s >= 100 && mutt1_s <= 25500)
  281. cl_mutt_param[1] = ((mutt1_s / 100) << 16) | ((mutt1_a / 100) << 8) | 1;
  282. if (mutt2_a == 0)
  283. cl_mutt_param[2] = 0;
  284. else if (mutt2_a >= 100 && mutt2_a <= 25500 && mutt2_s >= 100 && mutt2_s <= 25500)
  285. cl_mutt_param[2] = ((mutt2_s / 100) << 16) | ((mutt2_a / 100) << 8) | 1;
  286. if (mutt3_a == 0)
  287. cl_mutt_param[3] = 0;
  288. else if (mutt3_a >= 100 && mutt3_a <= 25500 && mutt3_s >= 100 && mutt3_s <= 25500)
  289. cl_mutt_param[3] = ((mutt3_s / 100) << 16) | ((mutt3_a / 100) << 8) | 1;
  290. return count;
  291. }
  292. #else
  293. #error "Change correspondent part when changing MAX_NUM_INSTANCE_MTK_COOLER_MUTT!"
  294. #endif
  295. mtk_cooler_3Gmutt_dprintk("[%s] bad arg\n", __func__);
  296. return -EINVAL;
  297. }
  298. static int _mtk_cl_mutt_proc_open(struct inode *inode, struct file *file)
  299. {
  300. return single_open(file, _mtk_cl_mutt_proc_read, NULL);
  301. }
  302. static const struct file_operations cl_3gmutt_fops = {
  303. .owner = THIS_MODULE,
  304. .open = _mtk_cl_mutt_proc_open,
  305. .read = seq_read,
  306. .llseek = seq_lseek,
  307. .write = _mtk_cl_mutt_proc_write,
  308. .release = single_release,
  309. };
  310. static int cl_debug_read(struct seq_file *m, void *v)
  311. {
  312. seq_printf(m, "[ cl_debug_read] cl_debug_flag = %d\n", cl_debug_flag);
  313. return 0;
  314. }
  315. static ssize_t cl_debug_write(struct file *file, const char __user *buffer, size_t count, loff_t *data)
  316. {
  317. char desc[32];
  318. int cl_debug_flag_switch;
  319. int cl_debug_flag_switch1;
  320. int cl_debug_flag_switch2;
  321. int len = 0;
  322. len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1);
  323. if (copy_from_user(desc, buffer, len))
  324. return 0;
  325. desc[len] = '\0';
  326. if (sscanf(desc, "%d %d %d", &cl_debug_flag_switch, &cl_debug_flag_switch1, &cl_debug_flag_switch2) == 3) {
  327. cl_debug_flag = cl_debug_flag_switch;
  328. mtk_cooler_3Gmutt_dprintk("cl_debug_write cl_debug_flag=%d\n", cl_debug_flag);
  329. /*return count;*/
  330. } else {
  331. mtk_cooler_3Gmutt_dprintk("cl_debug_write bad argument\n");
  332. }
  333. return -EINVAL;
  334. }
  335. static int cl_debug_open(struct inode *inode, struct file *file)
  336. {
  337. return single_open(file, cl_debug_read, NULL);
  338. }
  339. static const struct file_operations cl_debug_fops = {
  340. .owner = THIS_MODULE,
  341. .open = cl_debug_open,
  342. .read = seq_read,
  343. .llseek = seq_lseek,
  344. .write = cl_debug_write,
  345. .release = single_release,
  346. };
  347. static int __init mtk_cooler_mutt_init(void)
  348. {
  349. int err = 0;
  350. int i;
  351. for (i = MAX_NUM_INSTANCE_MTK_COOLER_3GMUTT; i-- > 0;) {
  352. cl_mutt_dev[i] = NULL;
  353. cl_mutt_state[i] = 0;
  354. }
  355. mtk_cooler_3Gmutt_dprintk("init\n");
  356. err = mtk_cooler_mutt_register_ltf();
  357. if (err)
  358. goto err_unreg;
  359. /* create a proc file */
  360. {
  361. struct proc_dir_entry *entry = NULL;
  362. struct proc_dir_entry *dir_entry = NULL;
  363. dir_entry = mtk_thermal_get_proc_drv_therm_dir_entry();
  364. if (!dir_entry) {
  365. mtk_cooler_3Gmutt_dprintk_always
  366. ("[%s]: mkdir /proc/driver/thermal failed\n", __func__);
  367. } else {
  368. entry =
  369. proc_create("cldebug", S_IRUGO | S_IWUSR | S_IWGRP, dir_entry,
  370. &cl_debug_fops);
  371. if (entry)
  372. proc_set_user(entry, uid, gid);
  373. entry =
  374. proc_create("cl3gmutt", S_IRUGO | S_IWUSR | S_IWGRP, dir_entry,
  375. &cl_3gmutt_fops);
  376. if (entry)
  377. proc_set_user(entry, uid, gid);
  378. entry =
  379. proc_create("tm_3Gpid", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, dir_entry,
  380. &mddulthro_pid_fops);
  381. if (entry)
  382. proc_set_user(entry, uid, gid);
  383. }
  384. }
  385. return 0;
  386. err_unreg:
  387. mtk_cooler_mutt_unregister_ltf();
  388. return err;
  389. }
  390. static void __exit mtk_cooler_mutt_exit(void)
  391. {
  392. mtk_cooler_3Gmutt_dprintk("exit\n");
  393. /* remove the proc file */
  394. remove_proc_entry("clmutt", NULL);
  395. mtk_cooler_mutt_unregister_ltf();
  396. }
  397. module_init(mtk_cooler_mutt_init);
  398. module_exit(mtk_cooler_mutt_exit);