windfarm_pm121.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Windfarm PowerMac thermal control. iMac G5 iSight
  4. *
  5. * (c) Copyright 2007 Étienne Bersac <[email protected]>
  6. *
  7. * Bits & pieces from windfarm_pm81.c by (c) Copyright 2005 Benjamin
  8. * Herrenschmidt, IBM Corp. <[email protected]>
  9. *
  10. * PowerMac12,1
  11. * ============
  12. *
  13. * The algorithm used is the PID control algorithm, used the same way
  14. * the published Darwin code does, using the same values that are
  15. * present in the Darwin 8.10 snapshot property lists (note however
  16. * that none of the code has been re-used, it's a complete
  17. * re-implementation
  18. *
  19. * There is two models using PowerMac12,1. Model 2 is iMac G5 iSight
  20. * 17" while Model 3 is iMac G5 20". They do have both the same
  21. * controls with a tiny difference. The control-ids of hard-drive-fan
  22. * and cpu-fan is swapped.
  23. *
  24. * Target Correction :
  25. *
  26. * controls have a target correction calculated as :
  27. *
  28. * new_min = ((((average_power * slope) >> 16) + offset) >> 16) + min_value
  29. * new_value = max(new_value, max(new_min, 0))
  30. *
  31. * OD Fan control correction.
  32. *
  33. * # model_id: 2
  34. * offset : -19563152
  35. * slope : 1956315
  36. *
  37. * # model_id: 3
  38. * offset : -15650652
  39. * slope : 1565065
  40. *
  41. * HD Fan control correction.
  42. *
  43. * # model_id: 2
  44. * offset : -15650652
  45. * slope : 1565065
  46. *
  47. * # model_id: 3
  48. * offset : -19563152
  49. * slope : 1956315
  50. *
  51. * CPU Fan control correction.
  52. *
  53. * # model_id: 2
  54. * offset : -25431900
  55. * slope : 2543190
  56. *
  57. * # model_id: 3
  58. * offset : -15650652
  59. * slope : 1565065
  60. *
  61. * Target rubber-banding :
  62. *
  63. * Some controls have a target correction which depends on another
  64. * control value. The correction is computed in the following way :
  65. *
  66. * new_min = ref_value * slope + offset
  67. *
  68. * ref_value is the value of the reference control. If new_min is
  69. * greater than 0, then we correct the target value using :
  70. *
  71. * new_target = max (new_target, new_min >> 16)
  72. *
  73. * # model_id : 2
  74. * control : cpu-fan
  75. * ref : optical-drive-fan
  76. * offset : -15650652
  77. * slope : 1565065
  78. *
  79. * # model_id : 3
  80. * control : optical-drive-fan
  81. * ref : hard-drive-fan
  82. * offset : -32768000
  83. * slope : 65536
  84. *
  85. * In order to have the moste efficient correction with those
  86. * dependencies, we must trigger HD loop before OD loop before CPU
  87. * loop.
  88. *
  89. * The various control loops found in Darwin config file are:
  90. *
  91. * HD Fan control loop.
  92. *
  93. * # model_id: 2
  94. * control : hard-drive-fan
  95. * sensor : hard-drive-temp
  96. * PID params : G_d = 0x00000000
  97. * G_p = 0x002D70A3
  98. * G_r = 0x00019999
  99. * History = 2 entries
  100. * Input target = 0x370000
  101. * Interval = 5s
  102. *
  103. * # model_id: 3
  104. * control : hard-drive-fan
  105. * sensor : hard-drive-temp
  106. * PID params : G_d = 0x00000000
  107. * G_p = 0x002170A3
  108. * G_r = 0x00019999
  109. * History = 2 entries
  110. * Input target = 0x370000
  111. * Interval = 5s
  112. *
  113. * OD Fan control loop.
  114. *
  115. * # model_id: 2
  116. * control : optical-drive-fan
  117. * sensor : optical-drive-temp
  118. * PID params : G_d = 0x00000000
  119. * G_p = 0x001FAE14
  120. * G_r = 0x00019999
  121. * History = 2 entries
  122. * Input target = 0x320000
  123. * Interval = 5s
  124. *
  125. * # model_id: 3
  126. * control : optical-drive-fan
  127. * sensor : optical-drive-temp
  128. * PID params : G_d = 0x00000000
  129. * G_p = 0x001FAE14
  130. * G_r = 0x00019999
  131. * History = 2 entries
  132. * Input target = 0x320000
  133. * Interval = 5s
  134. *
  135. * GPU Fan control loop.
  136. *
  137. * # model_id: 2
  138. * control : hard-drive-fan
  139. * sensor : gpu-temp
  140. * PID params : G_d = 0x00000000
  141. * G_p = 0x002A6666
  142. * G_r = 0x00019999
  143. * History = 2 entries
  144. * Input target = 0x5A0000
  145. * Interval = 5s
  146. *
  147. * # model_id: 3
  148. * control : cpu-fan
  149. * sensor : gpu-temp
  150. * PID params : G_d = 0x00000000
  151. * G_p = 0x0010CCCC
  152. * G_r = 0x00019999
  153. * History = 2 entries
  154. * Input target = 0x500000
  155. * Interval = 5s
  156. *
  157. * KODIAK (aka northbridge) Fan control loop.
  158. *
  159. * # model_id: 2
  160. * control : optical-drive-fan
  161. * sensor : north-bridge-temp
  162. * PID params : G_d = 0x00000000
  163. * G_p = 0x003BD70A
  164. * G_r = 0x00019999
  165. * History = 2 entries
  166. * Input target = 0x550000
  167. * Interval = 5s
  168. *
  169. * # model_id: 3
  170. * control : hard-drive-fan
  171. * sensor : north-bridge-temp
  172. * PID params : G_d = 0x00000000
  173. * G_p = 0x0030F5C2
  174. * G_r = 0x00019999
  175. * History = 2 entries
  176. * Input target = 0x550000
  177. * Interval = 5s
  178. *
  179. * CPU Fan control loop.
  180. *
  181. * control : cpu-fan
  182. * sensors : cpu-temp, cpu-power
  183. * PID params : from SDB partition
  184. *
  185. * CPU Slew control loop.
  186. *
  187. * control : cpufreq-clamp
  188. * sensor : cpu-temp
  189. */
  190. #undef DEBUG
  191. #include <linux/types.h>
  192. #include <linux/errno.h>
  193. #include <linux/kernel.h>
  194. #include <linux/delay.h>
  195. #include <linux/slab.h>
  196. #include <linux/init.h>
  197. #include <linux/spinlock.h>
  198. #include <linux/wait.h>
  199. #include <linux/kmod.h>
  200. #include <linux/device.h>
  201. #include <linux/platform_device.h>
  202. #include <linux/of.h>
  203. #include <asm/machdep.h>
  204. #include <asm/io.h>
  205. #include <asm/sections.h>
  206. #include <asm/smu.h>
  207. #include "windfarm.h"
  208. #include "windfarm_pid.h"
  209. #define VERSION "0.3"
  210. static int pm121_mach_model; /* machine model id */
  211. /* Controls & sensors */
  212. static struct wf_sensor *sensor_cpu_power;
  213. static struct wf_sensor *sensor_cpu_temp;
  214. static struct wf_sensor *sensor_cpu_voltage;
  215. static struct wf_sensor *sensor_cpu_current;
  216. static struct wf_sensor *sensor_gpu_temp;
  217. static struct wf_sensor *sensor_north_bridge_temp;
  218. static struct wf_sensor *sensor_hard_drive_temp;
  219. static struct wf_sensor *sensor_optical_drive_temp;
  220. static struct wf_sensor *sensor_incoming_air_temp; /* unused ! */
  221. enum {
  222. FAN_CPU,
  223. FAN_HD,
  224. FAN_OD,
  225. CPUFREQ,
  226. N_CONTROLS
  227. };
  228. static struct wf_control *controls[N_CONTROLS] = {};
  229. /* Set to kick the control loop into life */
  230. static int pm121_all_controls_ok, pm121_all_sensors_ok;
  231. static bool pm121_started;
  232. enum {
  233. FAILURE_FAN = 1 << 0,
  234. FAILURE_SENSOR = 1 << 1,
  235. FAILURE_OVERTEMP = 1 << 2
  236. };
  237. /* All sys loops. Note the HD before the OD loop in order to have it
  238. run before. */
  239. enum {
  240. LOOP_GPU, /* control = hd or cpu, but luckily,
  241. it doesn't matter */
  242. LOOP_HD, /* control = hd */
  243. LOOP_KODIAK, /* control = hd or od */
  244. LOOP_OD, /* control = od */
  245. N_LOOPS
  246. };
  247. static const char *loop_names[N_LOOPS] = {
  248. "GPU",
  249. "HD",
  250. "KODIAK",
  251. "OD",
  252. };
  253. #define PM121_NUM_CONFIGS 2
  254. static unsigned int pm121_failure_state;
  255. static int pm121_readjust, pm121_skipping;
  256. static bool pm121_overtemp;
  257. static s32 average_power;
  258. struct pm121_correction {
  259. int offset;
  260. int slope;
  261. };
  262. static struct pm121_correction corrections[N_CONTROLS][PM121_NUM_CONFIGS] = {
  263. /* FAN_OD */
  264. {
  265. /* MODEL 2 */
  266. { .offset = -19563152,
  267. .slope = 1956315
  268. },
  269. /* MODEL 3 */
  270. { .offset = -15650652,
  271. .slope = 1565065
  272. },
  273. },
  274. /* FAN_HD */
  275. {
  276. /* MODEL 2 */
  277. { .offset = -15650652,
  278. .slope = 1565065
  279. },
  280. /* MODEL 3 */
  281. { .offset = -19563152,
  282. .slope = 1956315
  283. },
  284. },
  285. /* FAN_CPU */
  286. {
  287. /* MODEL 2 */
  288. { .offset = -25431900,
  289. .slope = 2543190
  290. },
  291. /* MODEL 3 */
  292. { .offset = -15650652,
  293. .slope = 1565065
  294. },
  295. },
  296. /* CPUFREQ has no correction (and is not implemented at all) */
  297. };
  298. struct pm121_connection {
  299. unsigned int control_id;
  300. unsigned int ref_id;
  301. struct pm121_correction correction;
  302. };
  303. static struct pm121_connection pm121_connections[] = {
  304. /* MODEL 2 */
  305. { .control_id = FAN_CPU,
  306. .ref_id = FAN_OD,
  307. { .offset = -32768000,
  308. .slope = 65536
  309. }
  310. },
  311. /* MODEL 3 */
  312. { .control_id = FAN_OD,
  313. .ref_id = FAN_HD,
  314. { .offset = -32768000,
  315. .slope = 65536
  316. }
  317. },
  318. };
  319. /* pointer to the current model connection */
  320. static struct pm121_connection *pm121_connection;
  321. /*
  322. * ****** System Fans Control Loop ******
  323. *
  324. */
  325. /* Since each loop handles only one control and we want to avoid
  326. * writing virtual control, we store the control correction with the
  327. * loop params. Some data are not set, there are common to all loop
  328. * and thus, hardcoded.
  329. */
  330. struct pm121_sys_param {
  331. /* purely informative since we use mach_model-2 as index */
  332. int model_id;
  333. struct wf_sensor **sensor; /* use sensor_id instead ? */
  334. s32 gp, itarget;
  335. unsigned int control_id;
  336. };
  337. static struct pm121_sys_param
  338. pm121_sys_all_params[N_LOOPS][PM121_NUM_CONFIGS] = {
  339. /* GPU Fan control loop */
  340. {
  341. { .model_id = 2,
  342. .sensor = &sensor_gpu_temp,
  343. .gp = 0x002A6666,
  344. .itarget = 0x5A0000,
  345. .control_id = FAN_HD,
  346. },
  347. { .model_id = 3,
  348. .sensor = &sensor_gpu_temp,
  349. .gp = 0x0010CCCC,
  350. .itarget = 0x500000,
  351. .control_id = FAN_CPU,
  352. },
  353. },
  354. /* HD Fan control loop */
  355. {
  356. { .model_id = 2,
  357. .sensor = &sensor_hard_drive_temp,
  358. .gp = 0x002D70A3,
  359. .itarget = 0x370000,
  360. .control_id = FAN_HD,
  361. },
  362. { .model_id = 3,
  363. .sensor = &sensor_hard_drive_temp,
  364. .gp = 0x002170A3,
  365. .itarget = 0x370000,
  366. .control_id = FAN_HD,
  367. },
  368. },
  369. /* KODIAK Fan control loop */
  370. {
  371. { .model_id = 2,
  372. .sensor = &sensor_north_bridge_temp,
  373. .gp = 0x003BD70A,
  374. .itarget = 0x550000,
  375. .control_id = FAN_OD,
  376. },
  377. { .model_id = 3,
  378. .sensor = &sensor_north_bridge_temp,
  379. .gp = 0x0030F5C2,
  380. .itarget = 0x550000,
  381. .control_id = FAN_HD,
  382. },
  383. },
  384. /* OD Fan control loop */
  385. {
  386. { .model_id = 2,
  387. .sensor = &sensor_optical_drive_temp,
  388. .gp = 0x001FAE14,
  389. .itarget = 0x320000,
  390. .control_id = FAN_OD,
  391. },
  392. { .model_id = 3,
  393. .sensor = &sensor_optical_drive_temp,
  394. .gp = 0x001FAE14,
  395. .itarget = 0x320000,
  396. .control_id = FAN_OD,
  397. },
  398. },
  399. };
  400. /* the hardcoded values */
  401. #define PM121_SYS_GD 0x00000000
  402. #define PM121_SYS_GR 0x00019999
  403. #define PM121_SYS_HISTORY_SIZE 2
  404. #define PM121_SYS_INTERVAL 5
  405. /* State data used by the system fans control loop
  406. */
  407. struct pm121_sys_state {
  408. int ticks;
  409. s32 setpoint;
  410. struct wf_pid_state pid;
  411. };
  412. static struct pm121_sys_state *pm121_sys_state[N_LOOPS] = {};
  413. /*
  414. * ****** CPU Fans Control Loop ******
  415. *
  416. */
  417. #define PM121_CPU_INTERVAL 1
  418. /* State data used by the cpu fans control loop
  419. */
  420. struct pm121_cpu_state {
  421. int ticks;
  422. s32 setpoint;
  423. struct wf_cpu_pid_state pid;
  424. };
  425. static struct pm121_cpu_state *pm121_cpu_state;
  426. /*
  427. * ***** Implementation *****
  428. *
  429. */
  430. /* correction the value using the output-low-bound correction algo */
  431. static s32 pm121_correct(s32 new_setpoint,
  432. unsigned int control_id,
  433. s32 min)
  434. {
  435. s32 new_min;
  436. struct pm121_correction *correction;
  437. correction = &corrections[control_id][pm121_mach_model - 2];
  438. new_min = (average_power * correction->slope) >> 16;
  439. new_min += correction->offset;
  440. new_min = (new_min >> 16) + min;
  441. return max3(new_setpoint, new_min, 0);
  442. }
  443. static s32 pm121_connect(unsigned int control_id, s32 setpoint)
  444. {
  445. s32 new_min, value, new_setpoint;
  446. if (pm121_connection->control_id == control_id) {
  447. controls[control_id]->ops->get_value(controls[control_id],
  448. &value);
  449. new_min = value * pm121_connection->correction.slope;
  450. new_min += pm121_connection->correction.offset;
  451. if (new_min > 0) {
  452. new_setpoint = max(setpoint, (new_min >> 16));
  453. if (new_setpoint != setpoint) {
  454. pr_debug("pm121: %s depending on %s, "
  455. "corrected from %d to %d RPM\n",
  456. controls[control_id]->name,
  457. controls[pm121_connection->ref_id]->name,
  458. (int) setpoint, (int) new_setpoint);
  459. }
  460. } else
  461. new_setpoint = setpoint;
  462. }
  463. /* no connection */
  464. else
  465. new_setpoint = setpoint;
  466. return new_setpoint;
  467. }
  468. /* FAN LOOPS */
  469. static void pm121_create_sys_fans(int loop_id)
  470. {
  471. struct pm121_sys_param *param = NULL;
  472. struct wf_pid_param pid_param;
  473. struct wf_control *control = NULL;
  474. int i;
  475. /* First, locate the params for this model */
  476. for (i = 0; i < PM121_NUM_CONFIGS; i++) {
  477. if (pm121_sys_all_params[loop_id][i].model_id == pm121_mach_model) {
  478. param = &(pm121_sys_all_params[loop_id][i]);
  479. break;
  480. }
  481. }
  482. /* No params found, put fans to max */
  483. if (param == NULL) {
  484. printk(KERN_WARNING "pm121: %s fan config not found "
  485. " for this machine model\n",
  486. loop_names[loop_id]);
  487. goto fail;
  488. }
  489. control = controls[param->control_id];
  490. /* Alloc & initialize state */
  491. pm121_sys_state[loop_id] = kmalloc(sizeof(struct pm121_sys_state),
  492. GFP_KERNEL);
  493. if (pm121_sys_state[loop_id] == NULL) {
  494. printk(KERN_WARNING "pm121: Memory allocation error\n");
  495. goto fail;
  496. }
  497. pm121_sys_state[loop_id]->ticks = 1;
  498. /* Fill PID params */
  499. pid_param.gd = PM121_SYS_GD;
  500. pid_param.gp = param->gp;
  501. pid_param.gr = PM121_SYS_GR;
  502. pid_param.interval = PM121_SYS_INTERVAL;
  503. pid_param.history_len = PM121_SYS_HISTORY_SIZE;
  504. pid_param.itarget = param->itarget;
  505. if(control)
  506. {
  507. pid_param.min = control->ops->get_min(control);
  508. pid_param.max = control->ops->get_max(control);
  509. } else {
  510. /*
  511. * This is probably not the right!?
  512. * Perhaps goto fail if control == NULL above?
  513. */
  514. pid_param.min = 0;
  515. pid_param.max = 0;
  516. }
  517. wf_pid_init(&pm121_sys_state[loop_id]->pid, &pid_param);
  518. pr_debug("pm121: %s Fan control loop initialized.\n"
  519. " itarged=%d.%03d, min=%d RPM, max=%d RPM\n",
  520. loop_names[loop_id], FIX32TOPRINT(pid_param.itarget),
  521. pid_param.min, pid_param.max);
  522. return;
  523. fail:
  524. /* note that this is not optimal since another loop may still
  525. control the same control */
  526. printk(KERN_WARNING "pm121: failed to set up %s loop "
  527. "setting \"%s\" to max speed.\n",
  528. loop_names[loop_id], control ? control->name : "uninitialized value");
  529. if (control)
  530. wf_control_set_max(control);
  531. }
  532. static void pm121_sys_fans_tick(int loop_id)
  533. {
  534. struct pm121_sys_param *param;
  535. struct pm121_sys_state *st;
  536. struct wf_sensor *sensor;
  537. struct wf_control *control;
  538. s32 temp, new_setpoint;
  539. int rc;
  540. param = &(pm121_sys_all_params[loop_id][pm121_mach_model-2]);
  541. st = pm121_sys_state[loop_id];
  542. sensor = *(param->sensor);
  543. control = controls[param->control_id];
  544. if (--st->ticks != 0) {
  545. if (pm121_readjust)
  546. goto readjust;
  547. return;
  548. }
  549. st->ticks = PM121_SYS_INTERVAL;
  550. rc = sensor->ops->get_value(sensor, &temp);
  551. if (rc) {
  552. printk(KERN_WARNING "windfarm: %s sensor error %d\n",
  553. sensor->name, rc);
  554. pm121_failure_state |= FAILURE_SENSOR;
  555. return;
  556. }
  557. pr_debug("pm121: %s Fan tick ! %s: %d.%03d\n",
  558. loop_names[loop_id], sensor->name,
  559. FIX32TOPRINT(temp));
  560. new_setpoint = wf_pid_run(&st->pid, temp);
  561. /* correction */
  562. new_setpoint = pm121_correct(new_setpoint,
  563. param->control_id,
  564. st->pid.param.min);
  565. /* linked corretion */
  566. new_setpoint = pm121_connect(param->control_id, new_setpoint);
  567. if (new_setpoint == st->setpoint)
  568. return;
  569. st->setpoint = new_setpoint;
  570. pr_debug("pm121: %s corrected setpoint: %d RPM\n",
  571. control->name, (int)new_setpoint);
  572. readjust:
  573. if (control && pm121_failure_state == 0) {
  574. rc = control->ops->set_value(control, st->setpoint);
  575. if (rc) {
  576. printk(KERN_WARNING "windfarm: %s fan error %d\n",
  577. control->name, rc);
  578. pm121_failure_state |= FAILURE_FAN;
  579. }
  580. }
  581. }
  582. /* CPU LOOP */
  583. static void pm121_create_cpu_fans(void)
  584. {
  585. struct wf_cpu_pid_param pid_param;
  586. const struct smu_sdbp_header *hdr;
  587. struct smu_sdbp_cpupiddata *piddata;
  588. struct smu_sdbp_fvt *fvt;
  589. struct wf_control *fan_cpu;
  590. s32 tmax, tdelta, maxpow, powadj;
  591. fan_cpu = controls[FAN_CPU];
  592. /* First, locate the PID params in SMU SBD */
  593. hdr = smu_get_sdb_partition(SMU_SDB_CPUPIDDATA_ID, NULL);
  594. if (hdr == 0) {
  595. printk(KERN_WARNING "pm121: CPU PID fan config not found.\n");
  596. goto fail;
  597. }
  598. piddata = (struct smu_sdbp_cpupiddata *)&hdr[1];
  599. /* Get the FVT params for operating point 0 (the only supported one
  600. * for now) in order to get tmax
  601. */
  602. hdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL);
  603. if (hdr) {
  604. fvt = (struct smu_sdbp_fvt *)&hdr[1];
  605. tmax = ((s32)fvt->maxtemp) << 16;
  606. } else
  607. tmax = 0x5e0000; /* 94 degree default */
  608. /* Alloc & initialize state */
  609. pm121_cpu_state = kmalloc(sizeof(struct pm121_cpu_state),
  610. GFP_KERNEL);
  611. if (pm121_cpu_state == NULL)
  612. goto fail;
  613. pm121_cpu_state->ticks = 1;
  614. /* Fill PID params */
  615. pid_param.interval = PM121_CPU_INTERVAL;
  616. pid_param.history_len = piddata->history_len;
  617. if (pid_param.history_len > WF_CPU_PID_MAX_HISTORY) {
  618. printk(KERN_WARNING "pm121: History size overflow on "
  619. "CPU control loop (%d)\n", piddata->history_len);
  620. pid_param.history_len = WF_CPU_PID_MAX_HISTORY;
  621. }
  622. pid_param.gd = piddata->gd;
  623. pid_param.gp = piddata->gp;
  624. pid_param.gr = piddata->gr / pid_param.history_len;
  625. tdelta = ((s32)piddata->target_temp_delta) << 16;
  626. maxpow = ((s32)piddata->max_power) << 16;
  627. powadj = ((s32)piddata->power_adj) << 16;
  628. pid_param.tmax = tmax;
  629. pid_param.ttarget = tmax - tdelta;
  630. pid_param.pmaxadj = maxpow - powadj;
  631. pid_param.min = fan_cpu->ops->get_min(fan_cpu);
  632. pid_param.max = fan_cpu->ops->get_max(fan_cpu);
  633. wf_cpu_pid_init(&pm121_cpu_state->pid, &pid_param);
  634. pr_debug("pm121: CPU Fan control initialized.\n");
  635. pr_debug(" ttarget=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM,\n",
  636. FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax),
  637. pid_param.min, pid_param.max);
  638. return;
  639. fail:
  640. printk(KERN_WARNING "pm121: CPU fan config not found, max fan speed\n");
  641. if (controls[CPUFREQ])
  642. wf_control_set_max(controls[CPUFREQ]);
  643. if (fan_cpu)
  644. wf_control_set_max(fan_cpu);
  645. }
  646. static void pm121_cpu_fans_tick(struct pm121_cpu_state *st)
  647. {
  648. s32 new_setpoint, temp, power;
  649. struct wf_control *fan_cpu = NULL;
  650. int rc;
  651. if (--st->ticks != 0) {
  652. if (pm121_readjust)
  653. goto readjust;
  654. return;
  655. }
  656. st->ticks = PM121_CPU_INTERVAL;
  657. fan_cpu = controls[FAN_CPU];
  658. rc = sensor_cpu_temp->ops->get_value(sensor_cpu_temp, &temp);
  659. if (rc) {
  660. printk(KERN_WARNING "pm121: CPU temp sensor error %d\n",
  661. rc);
  662. pm121_failure_state |= FAILURE_SENSOR;
  663. return;
  664. }
  665. rc = sensor_cpu_power->ops->get_value(sensor_cpu_power, &power);
  666. if (rc) {
  667. printk(KERN_WARNING "pm121: CPU power sensor error %d\n",
  668. rc);
  669. pm121_failure_state |= FAILURE_SENSOR;
  670. return;
  671. }
  672. pr_debug("pm121: CPU Fans tick ! CPU temp: %d.%03d°C, power: %d.%03d\n",
  673. FIX32TOPRINT(temp), FIX32TOPRINT(power));
  674. if (temp > st->pid.param.tmax)
  675. pm121_failure_state |= FAILURE_OVERTEMP;
  676. new_setpoint = wf_cpu_pid_run(&st->pid, power, temp);
  677. /* correction */
  678. new_setpoint = pm121_correct(new_setpoint,
  679. FAN_CPU,
  680. st->pid.param.min);
  681. /* connected correction */
  682. new_setpoint = pm121_connect(FAN_CPU, new_setpoint);
  683. if (st->setpoint == new_setpoint)
  684. return;
  685. st->setpoint = new_setpoint;
  686. pr_debug("pm121: CPU corrected setpoint: %d RPM\n", (int)new_setpoint);
  687. readjust:
  688. if (fan_cpu && pm121_failure_state == 0) {
  689. rc = fan_cpu->ops->set_value(fan_cpu, st->setpoint);
  690. if (rc) {
  691. printk(KERN_WARNING "pm121: %s fan error %d\n",
  692. fan_cpu->name, rc);
  693. pm121_failure_state |= FAILURE_FAN;
  694. }
  695. }
  696. }
  697. /*
  698. * ****** Common ******
  699. *
  700. */
  701. static void pm121_tick(void)
  702. {
  703. unsigned int last_failure = pm121_failure_state;
  704. unsigned int new_failure;
  705. s32 total_power;
  706. int i;
  707. if (!pm121_started) {
  708. pr_debug("pm121: creating control loops !\n");
  709. for (i = 0; i < N_LOOPS; i++)
  710. pm121_create_sys_fans(i);
  711. pm121_create_cpu_fans();
  712. pm121_started = true;
  713. }
  714. /* skipping ticks */
  715. if (pm121_skipping && --pm121_skipping)
  716. return;
  717. /* compute average power */
  718. total_power = 0;
  719. for (i = 0; i < pm121_cpu_state->pid.param.history_len; i++)
  720. total_power += pm121_cpu_state->pid.powers[i];
  721. average_power = total_power / pm121_cpu_state->pid.param.history_len;
  722. pm121_failure_state = 0;
  723. for (i = 0 ; i < N_LOOPS; i++) {
  724. if (pm121_sys_state[i])
  725. pm121_sys_fans_tick(i);
  726. }
  727. if (pm121_cpu_state)
  728. pm121_cpu_fans_tick(pm121_cpu_state);
  729. pm121_readjust = 0;
  730. new_failure = pm121_failure_state & ~last_failure;
  731. /* If entering failure mode, clamp cpufreq and ramp all
  732. * fans to full speed.
  733. */
  734. if (pm121_failure_state && !last_failure) {
  735. for (i = 0; i < N_CONTROLS; i++) {
  736. if (controls[i])
  737. wf_control_set_max(controls[i]);
  738. }
  739. }
  740. /* If leaving failure mode, unclamp cpufreq and readjust
  741. * all fans on next iteration
  742. */
  743. if (!pm121_failure_state && last_failure) {
  744. if (controls[CPUFREQ])
  745. wf_control_set_min(controls[CPUFREQ]);
  746. pm121_readjust = 1;
  747. }
  748. /* Overtemp condition detected, notify and start skipping a couple
  749. * ticks to let the temperature go down
  750. */
  751. if (new_failure & FAILURE_OVERTEMP) {
  752. wf_set_overtemp();
  753. pm121_skipping = 2;
  754. pm121_overtemp = true;
  755. }
  756. /* We only clear the overtemp condition if overtemp is cleared
  757. * _and_ no other failure is present. Since a sensor error will
  758. * clear the overtemp condition (can't measure temperature) at
  759. * the control loop levels, but we don't want to keep it clear
  760. * here in this case
  761. */
  762. if (!pm121_failure_state && pm121_overtemp) {
  763. wf_clear_overtemp();
  764. pm121_overtemp = false;
  765. }
  766. }
  767. static struct wf_control* pm121_register_control(struct wf_control *ct,
  768. const char *match,
  769. unsigned int id)
  770. {
  771. if (controls[id] == NULL && !strcmp(ct->name, match)) {
  772. if (wf_get_control(ct) == 0)
  773. controls[id] = ct;
  774. }
  775. return controls[id];
  776. }
  777. static void pm121_new_control(struct wf_control *ct)
  778. {
  779. int all = 1;
  780. if (pm121_all_controls_ok)
  781. return;
  782. all = pm121_register_control(ct, "optical-drive-fan", FAN_OD) && all;
  783. all = pm121_register_control(ct, "hard-drive-fan", FAN_HD) && all;
  784. all = pm121_register_control(ct, "cpu-fan", FAN_CPU) && all;
  785. all = pm121_register_control(ct, "cpufreq-clamp", CPUFREQ) && all;
  786. if (all)
  787. pm121_all_controls_ok = 1;
  788. }
  789. static struct wf_sensor* pm121_register_sensor(struct wf_sensor *sensor,
  790. const char *match,
  791. struct wf_sensor **var)
  792. {
  793. if (*var == NULL && !strcmp(sensor->name, match)) {
  794. if (wf_get_sensor(sensor) == 0)
  795. *var = sensor;
  796. }
  797. return *var;
  798. }
  799. static void pm121_new_sensor(struct wf_sensor *sr)
  800. {
  801. int all = 1;
  802. if (pm121_all_sensors_ok)
  803. return;
  804. all = pm121_register_sensor(sr, "cpu-temp",
  805. &sensor_cpu_temp) && all;
  806. all = pm121_register_sensor(sr, "cpu-current",
  807. &sensor_cpu_current) && all;
  808. all = pm121_register_sensor(sr, "cpu-voltage",
  809. &sensor_cpu_voltage) && all;
  810. all = pm121_register_sensor(sr, "cpu-power",
  811. &sensor_cpu_power) && all;
  812. all = pm121_register_sensor(sr, "hard-drive-temp",
  813. &sensor_hard_drive_temp) && all;
  814. all = pm121_register_sensor(sr, "optical-drive-temp",
  815. &sensor_optical_drive_temp) && all;
  816. all = pm121_register_sensor(sr, "incoming-air-temp",
  817. &sensor_incoming_air_temp) && all;
  818. all = pm121_register_sensor(sr, "north-bridge-temp",
  819. &sensor_north_bridge_temp) && all;
  820. all = pm121_register_sensor(sr, "gpu-temp",
  821. &sensor_gpu_temp) && all;
  822. if (all)
  823. pm121_all_sensors_ok = 1;
  824. }
  825. static int pm121_notify(struct notifier_block *self,
  826. unsigned long event, void *data)
  827. {
  828. switch (event) {
  829. case WF_EVENT_NEW_CONTROL:
  830. pr_debug("pm121: new control %s detected\n",
  831. ((struct wf_control *)data)->name);
  832. pm121_new_control(data);
  833. break;
  834. case WF_EVENT_NEW_SENSOR:
  835. pr_debug("pm121: new sensor %s detected\n",
  836. ((struct wf_sensor *)data)->name);
  837. pm121_new_sensor(data);
  838. break;
  839. case WF_EVENT_TICK:
  840. if (pm121_all_controls_ok && pm121_all_sensors_ok)
  841. pm121_tick();
  842. break;
  843. }
  844. return 0;
  845. }
  846. static struct notifier_block pm121_events = {
  847. .notifier_call = pm121_notify,
  848. };
  849. static int pm121_init_pm(void)
  850. {
  851. const struct smu_sdbp_header *hdr;
  852. hdr = smu_get_sdb_partition(SMU_SDB_SENSORTREE_ID, NULL);
  853. if (hdr != 0) {
  854. struct smu_sdbp_sensortree *st =
  855. (struct smu_sdbp_sensortree *)&hdr[1];
  856. pm121_mach_model = st->model_id;
  857. }
  858. pm121_connection = &pm121_connections[pm121_mach_model - 2];
  859. printk(KERN_INFO "pm121: Initializing for iMac G5 iSight model ID %d\n",
  860. pm121_mach_model);
  861. return 0;
  862. }
  863. static int pm121_probe(struct platform_device *ddev)
  864. {
  865. wf_register_client(&pm121_events);
  866. return 0;
  867. }
  868. static int pm121_remove(struct platform_device *ddev)
  869. {
  870. wf_unregister_client(&pm121_events);
  871. return 0;
  872. }
  873. static struct platform_driver pm121_driver = {
  874. .probe = pm121_probe,
  875. .remove = pm121_remove,
  876. .driver = {
  877. .name = "windfarm",
  878. .bus = &platform_bus_type,
  879. },
  880. };
  881. static int __init pm121_init(void)
  882. {
  883. int rc = -ENODEV;
  884. if (of_machine_is_compatible("PowerMac12,1"))
  885. rc = pm121_init_pm();
  886. if (rc == 0) {
  887. request_module("windfarm_smu_controls");
  888. request_module("windfarm_smu_sensors");
  889. request_module("windfarm_smu_sat");
  890. request_module("windfarm_lm75_sensor");
  891. request_module("windfarm_max6690_sensor");
  892. request_module("windfarm_cpufreq_clamp");
  893. platform_driver_register(&pm121_driver);
  894. }
  895. return rc;
  896. }
  897. static void __exit pm121_exit(void)
  898. {
  899. platform_driver_unregister(&pm121_driver);
  900. }
  901. module_init(pm121_init);
  902. module_exit(pm121_exit);
  903. MODULE_AUTHOR("Étienne Bersac <[email protected]>");
  904. MODULE_DESCRIPTION("Thermal control logic for iMac G5 (iSight)");
  905. MODULE_LICENSE("GPL");