windfarm_pm112.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. /*
  2. * Windfarm PowerMac thermal control.
  3. * Control loops for machines with SMU and PPC970MP processors.
  4. *
  5. * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org>
  6. * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
  7. *
  8. * Use and redistribute under the terms of the GNU GPL v2.
  9. */
  10. #include <linux/types.h>
  11. #include <linux/errno.h>
  12. #include <linux/kernel.h>
  13. #include <linux/device.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/reboot.h>
  16. #include <asm/prom.h>
  17. #include <asm/smu.h>
  18. #include "windfarm.h"
  19. #include "windfarm_pid.h"
  20. #define VERSION "0.2"
  21. #define DEBUG
  22. #undef LOTSA_DEBUG
  23. #ifdef DEBUG
  24. #define DBG(args...) printk(args)
  25. #else
  26. #define DBG(args...) do { } while(0)
  27. #endif
  28. #ifdef LOTSA_DEBUG
  29. #define DBG_LOTS(args...) printk(args)
  30. #else
  31. #define DBG_LOTS(args...) do { } while(0)
  32. #endif
  33. /* define this to force CPU overtemp to 60 degree, useful for testing
  34. * the overtemp code
  35. */
  36. #undef HACKED_OVERTEMP
  37. /* We currently only handle 2 chips, 4 cores... */
  38. #define NR_CHIPS 2
  39. #define NR_CORES 4
  40. #define NR_CPU_FANS 3 * NR_CHIPS
  41. /* Controls and sensors */
  42. static struct wf_sensor *sens_cpu_temp[NR_CORES];
  43. static struct wf_sensor *sens_cpu_power[NR_CORES];
  44. static struct wf_sensor *hd_temp;
  45. static struct wf_sensor *slots_power;
  46. static struct wf_sensor *u4_temp;
  47. static struct wf_control *cpu_fans[NR_CPU_FANS];
  48. static char *cpu_fan_names[NR_CPU_FANS] = {
  49. "cpu-rear-fan-0",
  50. "cpu-rear-fan-1",
  51. "cpu-front-fan-0",
  52. "cpu-front-fan-1",
  53. "cpu-pump-0",
  54. "cpu-pump-1",
  55. };
  56. static struct wf_control *cpufreq_clamp;
  57. /* Second pump isn't required (and isn't actually present) */
  58. #define CPU_FANS_REQD (NR_CPU_FANS - 2)
  59. #define FIRST_PUMP 4
  60. #define LAST_PUMP 5
  61. /* We keep a temperature history for average calculation of 180s */
  62. #define CPU_TEMP_HIST_SIZE 180
  63. /* Scale factor for fan speed, *100 */
  64. static int cpu_fan_scale[NR_CPU_FANS] = {
  65. 100,
  66. 100,
  67. 97, /* inlet fans run at 97% of exhaust fan */
  68. 97,
  69. 100, /* updated later */
  70. 100, /* updated later */
  71. };
  72. static struct wf_control *backside_fan;
  73. static struct wf_control *slots_fan;
  74. static struct wf_control *drive_bay_fan;
  75. /* PID loop state */
  76. static struct wf_cpu_pid_state cpu_pid[NR_CORES];
  77. static u32 cpu_thist[CPU_TEMP_HIST_SIZE];
  78. static int cpu_thist_pt;
  79. static s64 cpu_thist_total;
  80. static s32 cpu_all_tmax = 100 << 16;
  81. static int cpu_last_target;
  82. static struct wf_pid_state backside_pid;
  83. static int backside_tick;
  84. static struct wf_pid_state slots_pid;
  85. static int slots_started;
  86. static struct wf_pid_state drive_bay_pid;
  87. static int drive_bay_tick;
  88. static int nr_cores;
  89. static int have_all_controls;
  90. static int have_all_sensors;
  91. static int started;
  92. static int failure_state;
  93. #define FAILURE_SENSOR 1
  94. #define FAILURE_FAN 2
  95. #define FAILURE_PERM 4
  96. #define FAILURE_LOW_OVERTEMP 8
  97. #define FAILURE_HIGH_OVERTEMP 16
  98. /* Overtemp values */
  99. #define LOW_OVER_AVERAGE 0
  100. #define LOW_OVER_IMMEDIATE (10 << 16)
  101. #define LOW_OVER_CLEAR ((-10) << 16)
  102. #define HIGH_OVER_IMMEDIATE (14 << 16)
  103. #define HIGH_OVER_AVERAGE (10 << 16)
  104. #define HIGH_OVER_IMMEDIATE (14 << 16)
  105. /* Implementation... */
  106. static int create_cpu_loop(int cpu)
  107. {
  108. int chip = cpu / 2;
  109. int core = cpu & 1;
  110. struct smu_sdbp_header *hdr;
  111. struct smu_sdbp_cpupiddata *piddata;
  112. struct wf_cpu_pid_param pid;
  113. struct wf_control *main_fan = cpu_fans[0];
  114. s32 tmax;
  115. int fmin;
  116. /* Get PID params from the appropriate SAT */
  117. hdr = smu_sat_get_sdb_partition(chip, 0xC8 + core, NULL);
  118. if (hdr == NULL) {
  119. printk(KERN_WARNING"windfarm: can't get CPU PID fan config\n");
  120. return -EINVAL;
  121. }
  122. piddata = (struct smu_sdbp_cpupiddata *)&hdr[1];
  123. /* Get FVT params to get Tmax; if not found, assume default */
  124. hdr = smu_sat_get_sdb_partition(chip, 0xC4 + core, NULL);
  125. if (hdr) {
  126. struct smu_sdbp_fvt *fvt = (struct smu_sdbp_fvt *)&hdr[1];
  127. tmax = fvt->maxtemp << 16;
  128. } else
  129. tmax = 95 << 16; /* default to 95 degrees C */
  130. /* We keep a global tmax for overtemp calculations */
  131. if (tmax < cpu_all_tmax)
  132. cpu_all_tmax = tmax;
  133. /*
  134. * Darwin has a minimum fan speed of 1000 rpm for the 4-way and
  135. * 515 for the 2-way. That appears to be overkill, so for now,
  136. * impose a minimum of 750 or 515.
  137. */
  138. fmin = (nr_cores > 2) ? 750 : 515;
  139. /* Initialize PID loop */
  140. pid.interval = 1; /* seconds */
  141. pid.history_len = piddata->history_len;
  142. pid.gd = piddata->gd;
  143. pid.gp = piddata->gp;
  144. pid.gr = piddata->gr / piddata->history_len;
  145. pid.pmaxadj = (piddata->max_power << 16) - (piddata->power_adj << 8);
  146. pid.ttarget = tmax - (piddata->target_temp_delta << 16);
  147. pid.tmax = tmax;
  148. pid.min = main_fan->ops->get_min(main_fan);
  149. pid.max = main_fan->ops->get_max(main_fan);
  150. if (pid.min < fmin)
  151. pid.min = fmin;
  152. wf_cpu_pid_init(&cpu_pid[cpu], &pid);
  153. return 0;
  154. }
  155. static void cpu_max_all_fans(void)
  156. {
  157. int i;
  158. /* We max all CPU fans in case of a sensor error. We also do the
  159. * cpufreq clamping now, even if it's supposedly done later by the
  160. * generic code anyway, we do it earlier here to react faster
  161. */
  162. if (cpufreq_clamp)
  163. wf_control_set_max(cpufreq_clamp);
  164. for (i = 0; i < NR_CPU_FANS; ++i)
  165. if (cpu_fans[i])
  166. wf_control_set_max(cpu_fans[i]);
  167. }
  168. static int cpu_check_overtemp(s32 temp)
  169. {
  170. int new_state = 0;
  171. s32 t_avg, t_old;
  172. /* First check for immediate overtemps */
  173. if (temp >= (cpu_all_tmax + LOW_OVER_IMMEDIATE)) {
  174. new_state |= FAILURE_LOW_OVERTEMP;
  175. if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
  176. printk(KERN_ERR "windfarm: Overtemp due to immediate CPU"
  177. " temperature !\n");
  178. }
  179. if (temp >= (cpu_all_tmax + HIGH_OVER_IMMEDIATE)) {
  180. new_state |= FAILURE_HIGH_OVERTEMP;
  181. if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
  182. printk(KERN_ERR "windfarm: Critical overtemp due to"
  183. " immediate CPU temperature !\n");
  184. }
  185. /* We calculate a history of max temperatures and use that for the
  186. * overtemp management
  187. */
  188. t_old = cpu_thist[cpu_thist_pt];
  189. cpu_thist[cpu_thist_pt] = temp;
  190. cpu_thist_pt = (cpu_thist_pt + 1) % CPU_TEMP_HIST_SIZE;
  191. cpu_thist_total -= t_old;
  192. cpu_thist_total += temp;
  193. t_avg = cpu_thist_total / CPU_TEMP_HIST_SIZE;
  194. DBG_LOTS("t_avg = %d.%03d (out: %d.%03d, in: %d.%03d)\n",
  195. FIX32TOPRINT(t_avg), FIX32TOPRINT(t_old), FIX32TOPRINT(temp));
  196. /* Now check for average overtemps */
  197. if (t_avg >= (cpu_all_tmax + LOW_OVER_AVERAGE)) {
  198. new_state |= FAILURE_LOW_OVERTEMP;
  199. if ((failure_state & FAILURE_LOW_OVERTEMP) == 0)
  200. printk(KERN_ERR "windfarm: Overtemp due to average CPU"
  201. " temperature !\n");
  202. }
  203. if (t_avg >= (cpu_all_tmax + HIGH_OVER_AVERAGE)) {
  204. new_state |= FAILURE_HIGH_OVERTEMP;
  205. if ((failure_state & FAILURE_HIGH_OVERTEMP) == 0)
  206. printk(KERN_ERR "windfarm: Critical overtemp due to"
  207. " average CPU temperature !\n");
  208. }
  209. /* Now handle overtemp conditions. We don't currently use the windfarm
  210. * overtemp handling core as it's not fully suited to the needs of those
  211. * new machine. This will be fixed later.
  212. */
  213. if (new_state) {
  214. /* High overtemp -> immediate shutdown */
  215. if (new_state & FAILURE_HIGH_OVERTEMP)
  216. machine_power_off();
  217. if ((failure_state & new_state) != new_state)
  218. cpu_max_all_fans();
  219. failure_state |= new_state;
  220. } else if ((failure_state & FAILURE_LOW_OVERTEMP) &&
  221. (temp < (cpu_all_tmax + LOW_OVER_CLEAR))) {
  222. printk(KERN_ERR "windfarm: Overtemp condition cleared !\n");
  223. failure_state &= ~FAILURE_LOW_OVERTEMP;
  224. }
  225. return failure_state & (FAILURE_LOW_OVERTEMP | FAILURE_HIGH_OVERTEMP);
  226. }
  227. static void cpu_fans_tick(void)
  228. {
  229. int err, cpu;
  230. s32 greatest_delta = 0;
  231. s32 temp, power, t_max = 0;
  232. int i, t, target = 0;
  233. struct wf_sensor *sr;
  234. struct wf_control *ct;
  235. struct wf_cpu_pid_state *sp;
  236. DBG_LOTS(KERN_DEBUG);
  237. for (cpu = 0; cpu < nr_cores; ++cpu) {
  238. /* Get CPU core temperature */
  239. sr = sens_cpu_temp[cpu];
  240. err = sr->ops->get_value(sr, &temp);
  241. if (err) {
  242. DBG("\n");
  243. printk(KERN_WARNING "windfarm: CPU %d temperature "
  244. "sensor error %d\n", cpu, err);
  245. failure_state |= FAILURE_SENSOR;
  246. cpu_max_all_fans();
  247. return;
  248. }
  249. /* Keep track of highest temp */
  250. t_max = max(t_max, temp);
  251. /* Get CPU power */
  252. sr = sens_cpu_power[cpu];
  253. err = sr->ops->get_value(sr, &power);
  254. if (err) {
  255. DBG("\n");
  256. printk(KERN_WARNING "windfarm: CPU %d power "
  257. "sensor error %d\n", cpu, err);
  258. failure_state |= FAILURE_SENSOR;
  259. cpu_max_all_fans();
  260. return;
  261. }
  262. /* Run PID */
  263. sp = &cpu_pid[cpu];
  264. t = wf_cpu_pid_run(sp, power, temp);
  265. if (cpu == 0 || sp->last_delta > greatest_delta) {
  266. greatest_delta = sp->last_delta;
  267. target = t;
  268. }
  269. DBG_LOTS("[%d] P=%d.%.3d T=%d.%.3d ",
  270. cpu, FIX32TOPRINT(power), FIX32TOPRINT(temp));
  271. }
  272. DBG_LOTS("fans = %d, t_max = %d.%03d\n", target, FIX32TOPRINT(t_max));
  273. /* Darwin limits decrease to 20 per iteration */
  274. if (target < (cpu_last_target - 20))
  275. target = cpu_last_target - 20;
  276. cpu_last_target = target;
  277. for (cpu = 0; cpu < nr_cores; ++cpu)
  278. cpu_pid[cpu].target = target;
  279. /* Handle possible overtemps */
  280. if (cpu_check_overtemp(t_max))
  281. return;
  282. /* Set fans */
  283. for (i = 0; i < NR_CPU_FANS; ++i) {
  284. ct = cpu_fans[i];
  285. if (ct == NULL)
  286. continue;
  287. err = ct->ops->set_value(ct, target * cpu_fan_scale[i] / 100);
  288. if (err) {
  289. printk(KERN_WARNING "windfarm: fan %s reports "
  290. "error %d\n", ct->name, err);
  291. failure_state |= FAILURE_FAN;
  292. break;
  293. }
  294. }
  295. }
  296. /* Backside/U4 fan */
  297. static struct wf_pid_param backside_param = {
  298. .interval = 5,
  299. .history_len = 2,
  300. .gd = 48 << 20,
  301. .gp = 5 << 20,
  302. .gr = 0,
  303. .itarget = 64 << 16,
  304. .additive = 1,
  305. };
  306. static void backside_fan_tick(void)
  307. {
  308. s32 temp;
  309. int speed;
  310. int err;
  311. if (!backside_fan || !u4_temp)
  312. return;
  313. if (!backside_tick) {
  314. /* first time; initialize things */
  315. backside_param.min = backside_fan->ops->get_min(backside_fan);
  316. backside_param.max = backside_fan->ops->get_max(backside_fan);
  317. wf_pid_init(&backside_pid, &backside_param);
  318. backside_tick = 1;
  319. }
  320. if (--backside_tick > 0)
  321. return;
  322. backside_tick = backside_pid.param.interval;
  323. err = u4_temp->ops->get_value(u4_temp, &temp);
  324. if (err) {
  325. printk(KERN_WARNING "windfarm: U4 temp sensor error %d\n",
  326. err);
  327. failure_state |= FAILURE_SENSOR;
  328. wf_control_set_max(backside_fan);
  329. return;
  330. }
  331. speed = wf_pid_run(&backside_pid, temp);
  332. DBG_LOTS("backside PID temp=%d.%.3d speed=%d\n",
  333. FIX32TOPRINT(temp), speed);
  334. err = backside_fan->ops->set_value(backside_fan, speed);
  335. if (err) {
  336. printk(KERN_WARNING "windfarm: backside fan error %d\n", err);
  337. failure_state |= FAILURE_FAN;
  338. }
  339. }
  340. /* Drive bay fan */
  341. static struct wf_pid_param drive_bay_prm = {
  342. .interval = 5,
  343. .history_len = 2,
  344. .gd = 30 << 20,
  345. .gp = 5 << 20,
  346. .gr = 0,
  347. .itarget = 40 << 16,
  348. .additive = 1,
  349. };
  350. static void drive_bay_fan_tick(void)
  351. {
  352. s32 temp;
  353. int speed;
  354. int err;
  355. if (!drive_bay_fan || !hd_temp)
  356. return;
  357. if (!drive_bay_tick) {
  358. /* first time; initialize things */
  359. drive_bay_prm.min = drive_bay_fan->ops->get_min(drive_bay_fan);
  360. drive_bay_prm.max = drive_bay_fan->ops->get_max(drive_bay_fan);
  361. wf_pid_init(&drive_bay_pid, &drive_bay_prm);
  362. drive_bay_tick = 1;
  363. }
  364. if (--drive_bay_tick > 0)
  365. return;
  366. drive_bay_tick = drive_bay_pid.param.interval;
  367. err = hd_temp->ops->get_value(hd_temp, &temp);
  368. if (err) {
  369. printk(KERN_WARNING "windfarm: drive bay temp sensor "
  370. "error %d\n", err);
  371. failure_state |= FAILURE_SENSOR;
  372. wf_control_set_max(drive_bay_fan);
  373. return;
  374. }
  375. speed = wf_pid_run(&drive_bay_pid, temp);
  376. DBG_LOTS("drive_bay PID temp=%d.%.3d speed=%d\n",
  377. FIX32TOPRINT(temp), speed);
  378. err = drive_bay_fan->ops->set_value(drive_bay_fan, speed);
  379. if (err) {
  380. printk(KERN_WARNING "windfarm: drive bay fan error %d\n", err);
  381. failure_state |= FAILURE_FAN;
  382. }
  383. }
  384. /* PCI slots area fan */
  385. /* This makes the fan speed proportional to the power consumed */
  386. static struct wf_pid_param slots_param = {
  387. .interval = 1,
  388. .history_len = 2,
  389. .gd = 0,
  390. .gp = 0,
  391. .gr = 0x1277952,
  392. .itarget = 0,
  393. .min = 1560,
  394. .max = 3510,
  395. };
  396. static void slots_fan_tick(void)
  397. {
  398. s32 power;
  399. int speed;
  400. int err;
  401. if (!slots_fan || !slots_power)
  402. return;
  403. if (!slots_started) {
  404. /* first time; initialize things */
  405. wf_pid_init(&slots_pid, &slots_param);
  406. slots_started = 1;
  407. }
  408. err = slots_power->ops->get_value(slots_power, &power);
  409. if (err) {
  410. printk(KERN_WARNING "windfarm: slots power sensor error %d\n",
  411. err);
  412. failure_state |= FAILURE_SENSOR;
  413. wf_control_set_max(slots_fan);
  414. return;
  415. }
  416. speed = wf_pid_run(&slots_pid, power);
  417. DBG_LOTS("slots PID power=%d.%.3d speed=%d\n",
  418. FIX32TOPRINT(power), speed);
  419. err = slots_fan->ops->set_value(slots_fan, speed);
  420. if (err) {
  421. printk(KERN_WARNING "windfarm: slots fan error %d\n", err);
  422. failure_state |= FAILURE_FAN;
  423. }
  424. }
  425. static void set_fail_state(void)
  426. {
  427. int i;
  428. if (cpufreq_clamp)
  429. wf_control_set_max(cpufreq_clamp);
  430. for (i = 0; i < NR_CPU_FANS; ++i)
  431. if (cpu_fans[i])
  432. wf_control_set_max(cpu_fans[i]);
  433. if (backside_fan)
  434. wf_control_set_max(backside_fan);
  435. if (slots_fan)
  436. wf_control_set_max(slots_fan);
  437. if (drive_bay_fan)
  438. wf_control_set_max(drive_bay_fan);
  439. }
  440. static void pm112_tick(void)
  441. {
  442. int i, last_failure;
  443. if (!started) {
  444. started = 1;
  445. for (i = 0; i < nr_cores; ++i) {
  446. if (create_cpu_loop(i) < 0) {
  447. failure_state = FAILURE_PERM;
  448. set_fail_state();
  449. break;
  450. }
  451. }
  452. DBG_LOTS("cpu_all_tmax=%d.%03d\n", FIX32TOPRINT(cpu_all_tmax));
  453. #ifdef HACKED_OVERTEMP
  454. cpu_all_tmax = 60 << 16;
  455. #endif
  456. }
  457. /* Permanent failure, bail out */
  458. if (failure_state & FAILURE_PERM)
  459. return;
  460. /* Clear all failure bits except low overtemp which will be eventually
  461. * cleared by the control loop itself
  462. */
  463. last_failure = failure_state;
  464. failure_state &= FAILURE_LOW_OVERTEMP;
  465. cpu_fans_tick();
  466. backside_fan_tick();
  467. slots_fan_tick();
  468. drive_bay_fan_tick();
  469. DBG_LOTS("last_failure: 0x%x, failure_state: %x\n",
  470. last_failure, failure_state);
  471. /* Check for failures. Any failure causes cpufreq clamping */
  472. if (failure_state && last_failure == 0 && cpufreq_clamp)
  473. wf_control_set_max(cpufreq_clamp);
  474. if (failure_state == 0 && last_failure && cpufreq_clamp)
  475. wf_control_set_min(cpufreq_clamp);
  476. /* That's it for now, we might want to deal with other failures
  477. * differently in the future though
  478. */
  479. }
  480. static void pm112_new_control(struct wf_control *ct)
  481. {
  482. int i, max_exhaust;
  483. if (cpufreq_clamp == NULL && !strcmp(ct->name, "cpufreq-clamp")) {
  484. if (wf_get_control(ct) == 0)
  485. cpufreq_clamp = ct;
  486. }
  487. for (i = 0; i < NR_CPU_FANS; ++i) {
  488. if (!strcmp(ct->name, cpu_fan_names[i])) {
  489. if (cpu_fans[i] == NULL && wf_get_control(ct) == 0)
  490. cpu_fans[i] = ct;
  491. break;
  492. }
  493. }
  494. if (i >= NR_CPU_FANS) {
  495. /* not a CPU fan, try the others */
  496. if (!strcmp(ct->name, "backside-fan")) {
  497. if (backside_fan == NULL && wf_get_control(ct) == 0)
  498. backside_fan = ct;
  499. } else if (!strcmp(ct->name, "slots-fan")) {
  500. if (slots_fan == NULL && wf_get_control(ct) == 0)
  501. slots_fan = ct;
  502. } else if (!strcmp(ct->name, "drive-bay-fan")) {
  503. if (drive_bay_fan == NULL && wf_get_control(ct) == 0)
  504. drive_bay_fan = ct;
  505. }
  506. return;
  507. }
  508. for (i = 0; i < CPU_FANS_REQD; ++i)
  509. if (cpu_fans[i] == NULL)
  510. return;
  511. /* work out pump scaling factors */
  512. max_exhaust = cpu_fans[0]->ops->get_max(cpu_fans[0]);
  513. for (i = FIRST_PUMP; i <= LAST_PUMP; ++i)
  514. if ((ct = cpu_fans[i]) != NULL)
  515. cpu_fan_scale[i] =
  516. ct->ops->get_max(ct) * 100 / max_exhaust;
  517. have_all_controls = 1;
  518. }
  519. static void pm112_new_sensor(struct wf_sensor *sr)
  520. {
  521. unsigned int i;
  522. if (have_all_sensors)
  523. return;
  524. if (!strncmp(sr->name, "cpu-temp-", 9)) {
  525. i = sr->name[9] - '0';
  526. if (sr->name[10] == 0 && i < NR_CORES &&
  527. sens_cpu_temp[i] == NULL && wf_get_sensor(sr) == 0)
  528. sens_cpu_temp[i] = sr;
  529. } else if (!strncmp(sr->name, "cpu-power-", 10)) {
  530. i = sr->name[10] - '0';
  531. if (sr->name[11] == 0 && i < NR_CORES &&
  532. sens_cpu_power[i] == NULL && wf_get_sensor(sr) == 0)
  533. sens_cpu_power[i] = sr;
  534. } else if (!strcmp(sr->name, "hd-temp")) {
  535. if (hd_temp == NULL && wf_get_sensor(sr) == 0)
  536. hd_temp = sr;
  537. } else if (!strcmp(sr->name, "slots-power")) {
  538. if (slots_power == NULL && wf_get_sensor(sr) == 0)
  539. slots_power = sr;
  540. } else if (!strcmp(sr->name, "u4-temp")) {
  541. if (u4_temp == NULL && wf_get_sensor(sr) == 0)
  542. u4_temp = sr;
  543. } else
  544. return;
  545. /* check if we have all the sensors we need */
  546. for (i = 0; i < nr_cores; ++i)
  547. if (sens_cpu_temp[i] == NULL || sens_cpu_power[i] == NULL)
  548. return;
  549. have_all_sensors = 1;
  550. }
  551. static int pm112_wf_notify(struct notifier_block *self,
  552. unsigned long event, void *data)
  553. {
  554. switch (event) {
  555. case WF_EVENT_NEW_SENSOR:
  556. pm112_new_sensor(data);
  557. break;
  558. case WF_EVENT_NEW_CONTROL:
  559. pm112_new_control(data);
  560. break;
  561. case WF_EVENT_TICK:
  562. if (have_all_controls && have_all_sensors)
  563. pm112_tick();
  564. }
  565. return 0;
  566. }
  567. static struct notifier_block pm112_events = {
  568. .notifier_call = pm112_wf_notify,
  569. };
  570. static int wf_pm112_probe(struct device *dev)
  571. {
  572. wf_register_client(&pm112_events);
  573. return 0;
  574. }
  575. static int wf_pm112_remove(struct device *dev)
  576. {
  577. wf_unregister_client(&pm112_events);
  578. /* should release all sensors and controls */
  579. return 0;
  580. }
  581. static struct device_driver wf_pm112_driver = {
  582. .name = "windfarm",
  583. .bus = &platform_bus_type,
  584. .probe = wf_pm112_probe,
  585. .remove = wf_pm112_remove,
  586. };
  587. static int __init wf_pm112_init(void)
  588. {
  589. struct device_node *cpu;
  590. if (!machine_is_compatible("PowerMac11,2"))
  591. return -ENODEV;
  592. /* Count the number of CPU cores */
  593. nr_cores = 0;
  594. for (cpu = NULL; (cpu = of_find_node_by_type(cpu, "cpu")) != NULL; )
  595. ++nr_cores;
  596. printk(KERN_INFO "windfarm: initializing for dual-core desktop G5\n");
  597. driver_register(&wf_pm112_driver);
  598. return 0;
  599. }
  600. static void __exit wf_pm112_exit(void)
  601. {
  602. driver_unregister(&wf_pm112_driver);
  603. }
  604. module_init(wf_pm112_init);
  605. module_exit(wf_pm112_exit);
  606. MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
  607. MODULE_DESCRIPTION("Thermal control for PowerMac11,2");
  608. MODULE_LICENSE("GPL");