0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191 #undef DEBUG
0192
0193 #include <linux/types.h>
0194 #include <linux/errno.h>
0195 #include <linux/kernel.h>
0196 #include <linux/delay.h>
0197 #include <linux/slab.h>
0198 #include <linux/init.h>
0199 #include <linux/spinlock.h>
0200 #include <linux/wait.h>
0201 #include <linux/kmod.h>
0202 #include <linux/device.h>
0203 #include <linux/platform_device.h>
0204 #include <linux/of.h>
0205
0206 #include <asm/machdep.h>
0207 #include <asm/io.h>
0208 #include <asm/sections.h>
0209 #include <asm/smu.h>
0210
0211 #include "windfarm.h"
0212 #include "windfarm_pid.h"
0213
0214 #define VERSION "0.3"
0215
0216 static int pm121_mach_model;
0217
0218
0219 static struct wf_sensor *sensor_cpu_power;
0220 static struct wf_sensor *sensor_cpu_temp;
0221 static struct wf_sensor *sensor_cpu_voltage;
0222 static struct wf_sensor *sensor_cpu_current;
0223 static struct wf_sensor *sensor_gpu_temp;
0224 static struct wf_sensor *sensor_north_bridge_temp;
0225 static struct wf_sensor *sensor_hard_drive_temp;
0226 static struct wf_sensor *sensor_optical_drive_temp;
0227 static struct wf_sensor *sensor_incoming_air_temp;
0228
0229 enum {
0230 FAN_CPU,
0231 FAN_HD,
0232 FAN_OD,
0233 CPUFREQ,
0234 N_CONTROLS
0235 };
0236 static struct wf_control *controls[N_CONTROLS] = {};
0237
0238
0239 static int pm121_all_controls_ok, pm121_all_sensors_ok;
0240 static bool pm121_started;
0241
0242 enum {
0243 FAILURE_FAN = 1 << 0,
0244 FAILURE_SENSOR = 1 << 1,
0245 FAILURE_OVERTEMP = 1 << 2
0246 };
0247
0248
0249
0250 enum {
0251 LOOP_GPU,
0252
0253 LOOP_HD,
0254 LOOP_KODIAK,
0255 LOOP_OD,
0256 N_LOOPS
0257 };
0258
0259 static const char *loop_names[N_LOOPS] = {
0260 "GPU",
0261 "HD",
0262 "KODIAK",
0263 "OD",
0264 };
0265
0266 #define PM121_NUM_CONFIGS 2
0267
0268 static unsigned int pm121_failure_state;
0269 static int pm121_readjust, pm121_skipping;
0270 static bool pm121_overtemp;
0271 static s32 average_power;
0272
0273 struct pm121_correction {
0274 int offset;
0275 int slope;
0276 };
0277
0278 static struct pm121_correction corrections[N_CONTROLS][PM121_NUM_CONFIGS] = {
0279
0280 {
0281
0282 { .offset = -19563152,
0283 .slope = 1956315
0284 },
0285
0286 { .offset = -15650652,
0287 .slope = 1565065
0288 },
0289 },
0290
0291 {
0292
0293 { .offset = -15650652,
0294 .slope = 1565065
0295 },
0296
0297 { .offset = -19563152,
0298 .slope = 1956315
0299 },
0300 },
0301
0302 {
0303
0304 { .offset = -25431900,
0305 .slope = 2543190
0306 },
0307
0308 { .offset = -15650652,
0309 .slope = 1565065
0310 },
0311 },
0312
0313 };
0314
0315 struct pm121_connection {
0316 unsigned int control_id;
0317 unsigned int ref_id;
0318 struct pm121_correction correction;
0319 };
0320
0321 static struct pm121_connection pm121_connections[] = {
0322
0323 { .control_id = FAN_CPU,
0324 .ref_id = FAN_OD,
0325 { .offset = -32768000,
0326 .slope = 65536
0327 }
0328 },
0329
0330 { .control_id = FAN_OD,
0331 .ref_id = FAN_HD,
0332 { .offset = -32768000,
0333 .slope = 65536
0334 }
0335 },
0336 };
0337
0338
0339 static struct pm121_connection *pm121_connection;
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351 struct pm121_sys_param {
0352
0353 int model_id;
0354 struct wf_sensor **sensor;
0355 s32 gp, itarget;
0356 unsigned int control_id;
0357 };
0358
0359 static struct pm121_sys_param
0360 pm121_sys_all_params[N_LOOPS][PM121_NUM_CONFIGS] = {
0361
0362 {
0363 { .model_id = 2,
0364 .sensor = &sensor_gpu_temp,
0365 .gp = 0x002A6666,
0366 .itarget = 0x5A0000,
0367 .control_id = FAN_HD,
0368 },
0369 { .model_id = 3,
0370 .sensor = &sensor_gpu_temp,
0371 .gp = 0x0010CCCC,
0372 .itarget = 0x500000,
0373 .control_id = FAN_CPU,
0374 },
0375 },
0376
0377 {
0378 { .model_id = 2,
0379 .sensor = &sensor_hard_drive_temp,
0380 .gp = 0x002D70A3,
0381 .itarget = 0x370000,
0382 .control_id = FAN_HD,
0383 },
0384 { .model_id = 3,
0385 .sensor = &sensor_hard_drive_temp,
0386 .gp = 0x002170A3,
0387 .itarget = 0x370000,
0388 .control_id = FAN_HD,
0389 },
0390 },
0391
0392 {
0393 { .model_id = 2,
0394 .sensor = &sensor_north_bridge_temp,
0395 .gp = 0x003BD70A,
0396 .itarget = 0x550000,
0397 .control_id = FAN_OD,
0398 },
0399 { .model_id = 3,
0400 .sensor = &sensor_north_bridge_temp,
0401 .gp = 0x0030F5C2,
0402 .itarget = 0x550000,
0403 .control_id = FAN_HD,
0404 },
0405 },
0406
0407 {
0408 { .model_id = 2,
0409 .sensor = &sensor_optical_drive_temp,
0410 .gp = 0x001FAE14,
0411 .itarget = 0x320000,
0412 .control_id = FAN_OD,
0413 },
0414 { .model_id = 3,
0415 .sensor = &sensor_optical_drive_temp,
0416 .gp = 0x001FAE14,
0417 .itarget = 0x320000,
0418 .control_id = FAN_OD,
0419 },
0420 },
0421 };
0422
0423
0424 #define PM121_SYS_GD 0x00000000
0425 #define PM121_SYS_GR 0x00019999
0426 #define PM121_SYS_HISTORY_SIZE 2
0427 #define PM121_SYS_INTERVAL 5
0428
0429
0430
0431 struct pm121_sys_state {
0432 int ticks;
0433 s32 setpoint;
0434 struct wf_pid_state pid;
0435 };
0436
0437 static struct pm121_sys_state *pm121_sys_state[N_LOOPS] = {};
0438
0439
0440
0441
0442
0443
0444 #define PM121_CPU_INTERVAL 1
0445
0446
0447
0448 struct pm121_cpu_state {
0449 int ticks;
0450 s32 setpoint;
0451 struct wf_cpu_pid_state pid;
0452 };
0453
0454 static struct pm121_cpu_state *pm121_cpu_state;
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464 static s32 pm121_correct(s32 new_setpoint,
0465 unsigned int control_id,
0466 s32 min)
0467 {
0468 s32 new_min;
0469 struct pm121_correction *correction;
0470 correction = &corrections[control_id][pm121_mach_model - 2];
0471
0472 new_min = (average_power * correction->slope) >> 16;
0473 new_min += correction->offset;
0474 new_min = (new_min >> 16) + min;
0475
0476 return max3(new_setpoint, new_min, 0);
0477 }
0478
0479 static s32 pm121_connect(unsigned int control_id, s32 setpoint)
0480 {
0481 s32 new_min, value, new_setpoint;
0482
0483 if (pm121_connection->control_id == control_id) {
0484 controls[control_id]->ops->get_value(controls[control_id],
0485 &value);
0486 new_min = value * pm121_connection->correction.slope;
0487 new_min += pm121_connection->correction.offset;
0488 if (new_min > 0) {
0489 new_setpoint = max(setpoint, (new_min >> 16));
0490 if (new_setpoint != setpoint) {
0491 pr_debug("pm121: %s depending on %s, "
0492 "corrected from %d to %d RPM\n",
0493 controls[control_id]->name,
0494 controls[pm121_connection->ref_id]->name,
0495 (int) setpoint, (int) new_setpoint);
0496 }
0497 } else
0498 new_setpoint = setpoint;
0499 }
0500
0501 else
0502 new_setpoint = setpoint;
0503
0504 return new_setpoint;
0505 }
0506
0507
0508 static void pm121_create_sys_fans(int loop_id)
0509 {
0510 struct pm121_sys_param *param = NULL;
0511 struct wf_pid_param pid_param;
0512 struct wf_control *control = NULL;
0513 int i;
0514
0515
0516 for (i = 0; i < PM121_NUM_CONFIGS; i++) {
0517 if (pm121_sys_all_params[loop_id][i].model_id == pm121_mach_model) {
0518 param = &(pm121_sys_all_params[loop_id][i]);
0519 break;
0520 }
0521 }
0522
0523
0524 if (param == NULL) {
0525 printk(KERN_WARNING "pm121: %s fan config not found "
0526 " for this machine model\n",
0527 loop_names[loop_id]);
0528 goto fail;
0529 }
0530
0531 control = controls[param->control_id];
0532
0533
0534 pm121_sys_state[loop_id] = kmalloc(sizeof(struct pm121_sys_state),
0535 GFP_KERNEL);
0536 if (pm121_sys_state[loop_id] == NULL) {
0537 printk(KERN_WARNING "pm121: Memory allocation error\n");
0538 goto fail;
0539 }
0540 pm121_sys_state[loop_id]->ticks = 1;
0541
0542
0543 pid_param.gd = PM121_SYS_GD;
0544 pid_param.gp = param->gp;
0545 pid_param.gr = PM121_SYS_GR;
0546 pid_param.interval = PM121_SYS_INTERVAL;
0547 pid_param.history_len = PM121_SYS_HISTORY_SIZE;
0548 pid_param.itarget = param->itarget;
0549 if(control)
0550 {
0551 pid_param.min = control->ops->get_min(control);
0552 pid_param.max = control->ops->get_max(control);
0553 } else {
0554
0555
0556
0557
0558 pid_param.min = 0;
0559 pid_param.max = 0;
0560 }
0561
0562 wf_pid_init(&pm121_sys_state[loop_id]->pid, &pid_param);
0563
0564 pr_debug("pm121: %s Fan control loop initialized.\n"
0565 " itarged=%d.%03d, min=%d RPM, max=%d RPM\n",
0566 loop_names[loop_id], FIX32TOPRINT(pid_param.itarget),
0567 pid_param.min, pid_param.max);
0568 return;
0569
0570 fail:
0571
0572
0573 printk(KERN_WARNING "pm121: failed to set up %s loop "
0574 "setting \"%s\" to max speed.\n",
0575 loop_names[loop_id], control ? control->name : "uninitialized value");
0576
0577 if (control)
0578 wf_control_set_max(control);
0579 }
0580
0581 static void pm121_sys_fans_tick(int loop_id)
0582 {
0583 struct pm121_sys_param *param;
0584 struct pm121_sys_state *st;
0585 struct wf_sensor *sensor;
0586 struct wf_control *control;
0587 s32 temp, new_setpoint;
0588 int rc;
0589
0590 param = &(pm121_sys_all_params[loop_id][pm121_mach_model-2]);
0591 st = pm121_sys_state[loop_id];
0592 sensor = *(param->sensor);
0593 control = controls[param->control_id];
0594
0595 if (--st->ticks != 0) {
0596 if (pm121_readjust)
0597 goto readjust;
0598 return;
0599 }
0600 st->ticks = PM121_SYS_INTERVAL;
0601
0602 rc = sensor->ops->get_value(sensor, &temp);
0603 if (rc) {
0604 printk(KERN_WARNING "windfarm: %s sensor error %d\n",
0605 sensor->name, rc);
0606 pm121_failure_state |= FAILURE_SENSOR;
0607 return;
0608 }
0609
0610 pr_debug("pm121: %s Fan tick ! %s: %d.%03d\n",
0611 loop_names[loop_id], sensor->name,
0612 FIX32TOPRINT(temp));
0613
0614 new_setpoint = wf_pid_run(&st->pid, temp);
0615
0616
0617 new_setpoint = pm121_correct(new_setpoint,
0618 param->control_id,
0619 st->pid.param.min);
0620
0621 new_setpoint = pm121_connect(param->control_id, new_setpoint);
0622
0623 if (new_setpoint == st->setpoint)
0624 return;
0625 st->setpoint = new_setpoint;
0626 pr_debug("pm121: %s corrected setpoint: %d RPM\n",
0627 control->name, (int)new_setpoint);
0628 readjust:
0629 if (control && pm121_failure_state == 0) {
0630 rc = control->ops->set_value(control, st->setpoint);
0631 if (rc) {
0632 printk(KERN_WARNING "windfarm: %s fan error %d\n",
0633 control->name, rc);
0634 pm121_failure_state |= FAILURE_FAN;
0635 }
0636 }
0637 }
0638
0639
0640
0641 static void pm121_create_cpu_fans(void)
0642 {
0643 struct wf_cpu_pid_param pid_param;
0644 const struct smu_sdbp_header *hdr;
0645 struct smu_sdbp_cpupiddata *piddata;
0646 struct smu_sdbp_fvt *fvt;
0647 struct wf_control *fan_cpu;
0648 s32 tmax, tdelta, maxpow, powadj;
0649
0650 fan_cpu = controls[FAN_CPU];
0651
0652
0653 hdr = smu_get_sdb_partition(SMU_SDB_CPUPIDDATA_ID, NULL);
0654 if (hdr == 0) {
0655 printk(KERN_WARNING "pm121: CPU PID fan config not found.\n");
0656 goto fail;
0657 }
0658 piddata = (struct smu_sdbp_cpupiddata *)&hdr[1];
0659
0660
0661
0662
0663 hdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL);
0664 if (hdr) {
0665 fvt = (struct smu_sdbp_fvt *)&hdr[1];
0666 tmax = ((s32)fvt->maxtemp) << 16;
0667 } else
0668 tmax = 0x5e0000;
0669
0670
0671 pm121_cpu_state = kmalloc(sizeof(struct pm121_cpu_state),
0672 GFP_KERNEL);
0673 if (pm121_cpu_state == NULL)
0674 goto fail;
0675 pm121_cpu_state->ticks = 1;
0676
0677
0678 pid_param.interval = PM121_CPU_INTERVAL;
0679 pid_param.history_len = piddata->history_len;
0680 if (pid_param.history_len > WF_CPU_PID_MAX_HISTORY) {
0681 printk(KERN_WARNING "pm121: History size overflow on "
0682 "CPU control loop (%d)\n", piddata->history_len);
0683 pid_param.history_len = WF_CPU_PID_MAX_HISTORY;
0684 }
0685 pid_param.gd = piddata->gd;
0686 pid_param.gp = piddata->gp;
0687 pid_param.gr = piddata->gr / pid_param.history_len;
0688
0689 tdelta = ((s32)piddata->target_temp_delta) << 16;
0690 maxpow = ((s32)piddata->max_power) << 16;
0691 powadj = ((s32)piddata->power_adj) << 16;
0692
0693 pid_param.tmax = tmax;
0694 pid_param.ttarget = tmax - tdelta;
0695 pid_param.pmaxadj = maxpow - powadj;
0696
0697 pid_param.min = fan_cpu->ops->get_min(fan_cpu);
0698 pid_param.max = fan_cpu->ops->get_max(fan_cpu);
0699
0700 wf_cpu_pid_init(&pm121_cpu_state->pid, &pid_param);
0701
0702 pr_debug("pm121: CPU Fan control initialized.\n");
0703 pr_debug(" ttarget=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM,\n",
0704 FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax),
0705 pid_param.min, pid_param.max);
0706
0707 return;
0708
0709 fail:
0710 printk(KERN_WARNING "pm121: CPU fan config not found, max fan speed\n");
0711
0712 if (controls[CPUFREQ])
0713 wf_control_set_max(controls[CPUFREQ]);
0714 if (fan_cpu)
0715 wf_control_set_max(fan_cpu);
0716 }
0717
0718
0719 static void pm121_cpu_fans_tick(struct pm121_cpu_state *st)
0720 {
0721 s32 new_setpoint, temp, power;
0722 struct wf_control *fan_cpu = NULL;
0723 int rc;
0724
0725 if (--st->ticks != 0) {
0726 if (pm121_readjust)
0727 goto readjust;
0728 return;
0729 }
0730 st->ticks = PM121_CPU_INTERVAL;
0731
0732 fan_cpu = controls[FAN_CPU];
0733
0734 rc = sensor_cpu_temp->ops->get_value(sensor_cpu_temp, &temp);
0735 if (rc) {
0736 printk(KERN_WARNING "pm121: CPU temp sensor error %d\n",
0737 rc);
0738 pm121_failure_state |= FAILURE_SENSOR;
0739 return;
0740 }
0741
0742 rc = sensor_cpu_power->ops->get_value(sensor_cpu_power, &power);
0743 if (rc) {
0744 printk(KERN_WARNING "pm121: CPU power sensor error %d\n",
0745 rc);
0746 pm121_failure_state |= FAILURE_SENSOR;
0747 return;
0748 }
0749
0750 pr_debug("pm121: CPU Fans tick ! CPU temp: %d.%03d°C, power: %d.%03d\n",
0751 FIX32TOPRINT(temp), FIX32TOPRINT(power));
0752
0753 if (temp > st->pid.param.tmax)
0754 pm121_failure_state |= FAILURE_OVERTEMP;
0755
0756 new_setpoint = wf_cpu_pid_run(&st->pid, power, temp);
0757
0758
0759 new_setpoint = pm121_correct(new_setpoint,
0760 FAN_CPU,
0761 st->pid.param.min);
0762
0763
0764 new_setpoint = pm121_connect(FAN_CPU, new_setpoint);
0765
0766 if (st->setpoint == new_setpoint)
0767 return;
0768 st->setpoint = new_setpoint;
0769 pr_debug("pm121: CPU corrected setpoint: %d RPM\n", (int)new_setpoint);
0770
0771 readjust:
0772 if (fan_cpu && pm121_failure_state == 0) {
0773 rc = fan_cpu->ops->set_value(fan_cpu, st->setpoint);
0774 if (rc) {
0775 printk(KERN_WARNING "pm121: %s fan error %d\n",
0776 fan_cpu->name, rc);
0777 pm121_failure_state |= FAILURE_FAN;
0778 }
0779 }
0780 }
0781
0782
0783
0784
0785
0786
0787 static void pm121_tick(void)
0788 {
0789 unsigned int last_failure = pm121_failure_state;
0790 unsigned int new_failure;
0791 s32 total_power;
0792 int i;
0793
0794 if (!pm121_started) {
0795 pr_debug("pm121: creating control loops !\n");
0796 for (i = 0; i < N_LOOPS; i++)
0797 pm121_create_sys_fans(i);
0798
0799 pm121_create_cpu_fans();
0800 pm121_started = true;
0801 }
0802
0803
0804 if (pm121_skipping && --pm121_skipping)
0805 return;
0806
0807
0808 total_power = 0;
0809 for (i = 0; i < pm121_cpu_state->pid.param.history_len; i++)
0810 total_power += pm121_cpu_state->pid.powers[i];
0811
0812 average_power = total_power / pm121_cpu_state->pid.param.history_len;
0813
0814
0815 pm121_failure_state = 0;
0816 for (i = 0 ; i < N_LOOPS; i++) {
0817 if (pm121_sys_state[i])
0818 pm121_sys_fans_tick(i);
0819 }
0820
0821 if (pm121_cpu_state)
0822 pm121_cpu_fans_tick(pm121_cpu_state);
0823
0824 pm121_readjust = 0;
0825 new_failure = pm121_failure_state & ~last_failure;
0826
0827
0828
0829
0830 if (pm121_failure_state && !last_failure) {
0831 for (i = 0; i < N_CONTROLS; i++) {
0832 if (controls[i])
0833 wf_control_set_max(controls[i]);
0834 }
0835 }
0836
0837
0838
0839
0840 if (!pm121_failure_state && last_failure) {
0841 if (controls[CPUFREQ])
0842 wf_control_set_min(controls[CPUFREQ]);
0843 pm121_readjust = 1;
0844 }
0845
0846
0847
0848
0849 if (new_failure & FAILURE_OVERTEMP) {
0850 wf_set_overtemp();
0851 pm121_skipping = 2;
0852 pm121_overtemp = true;
0853 }
0854
0855
0856
0857
0858
0859
0860
0861 if (!pm121_failure_state && pm121_overtemp) {
0862 wf_clear_overtemp();
0863 pm121_overtemp = false;
0864 }
0865 }
0866
0867
0868 static struct wf_control* pm121_register_control(struct wf_control *ct,
0869 const char *match,
0870 unsigned int id)
0871 {
0872 if (controls[id] == NULL && !strcmp(ct->name, match)) {
0873 if (wf_get_control(ct) == 0)
0874 controls[id] = ct;
0875 }
0876 return controls[id];
0877 }
0878
0879 static void pm121_new_control(struct wf_control *ct)
0880 {
0881 int all = 1;
0882
0883 if (pm121_all_controls_ok)
0884 return;
0885
0886 all = pm121_register_control(ct, "optical-drive-fan", FAN_OD) && all;
0887 all = pm121_register_control(ct, "hard-drive-fan", FAN_HD) && all;
0888 all = pm121_register_control(ct, "cpu-fan", FAN_CPU) && all;
0889 all = pm121_register_control(ct, "cpufreq-clamp", CPUFREQ) && all;
0890
0891 if (all)
0892 pm121_all_controls_ok = 1;
0893 }
0894
0895
0896
0897
0898 static struct wf_sensor* pm121_register_sensor(struct wf_sensor *sensor,
0899 const char *match,
0900 struct wf_sensor **var)
0901 {
0902 if (*var == NULL && !strcmp(sensor->name, match)) {
0903 if (wf_get_sensor(sensor) == 0)
0904 *var = sensor;
0905 }
0906 return *var;
0907 }
0908
0909 static void pm121_new_sensor(struct wf_sensor *sr)
0910 {
0911 int all = 1;
0912
0913 if (pm121_all_sensors_ok)
0914 return;
0915
0916 all = pm121_register_sensor(sr, "cpu-temp",
0917 &sensor_cpu_temp) && all;
0918 all = pm121_register_sensor(sr, "cpu-current",
0919 &sensor_cpu_current) && all;
0920 all = pm121_register_sensor(sr, "cpu-voltage",
0921 &sensor_cpu_voltage) && all;
0922 all = pm121_register_sensor(sr, "cpu-power",
0923 &sensor_cpu_power) && all;
0924 all = pm121_register_sensor(sr, "hard-drive-temp",
0925 &sensor_hard_drive_temp) && all;
0926 all = pm121_register_sensor(sr, "optical-drive-temp",
0927 &sensor_optical_drive_temp) && all;
0928 all = pm121_register_sensor(sr, "incoming-air-temp",
0929 &sensor_incoming_air_temp) && all;
0930 all = pm121_register_sensor(sr, "north-bridge-temp",
0931 &sensor_north_bridge_temp) && all;
0932 all = pm121_register_sensor(sr, "gpu-temp",
0933 &sensor_gpu_temp) && all;
0934
0935 if (all)
0936 pm121_all_sensors_ok = 1;
0937 }
0938
0939
0940
0941 static int pm121_notify(struct notifier_block *self,
0942 unsigned long event, void *data)
0943 {
0944 switch (event) {
0945 case WF_EVENT_NEW_CONTROL:
0946 pr_debug("pm121: new control %s detected\n",
0947 ((struct wf_control *)data)->name);
0948 pm121_new_control(data);
0949 break;
0950 case WF_EVENT_NEW_SENSOR:
0951 pr_debug("pm121: new sensor %s detected\n",
0952 ((struct wf_sensor *)data)->name);
0953 pm121_new_sensor(data);
0954 break;
0955 case WF_EVENT_TICK:
0956 if (pm121_all_controls_ok && pm121_all_sensors_ok)
0957 pm121_tick();
0958 break;
0959 }
0960
0961 return 0;
0962 }
0963
0964 static struct notifier_block pm121_events = {
0965 .notifier_call = pm121_notify,
0966 };
0967
0968 static int pm121_init_pm(void)
0969 {
0970 const struct smu_sdbp_header *hdr;
0971
0972 hdr = smu_get_sdb_partition(SMU_SDB_SENSORTREE_ID, NULL);
0973 if (hdr != 0) {
0974 struct smu_sdbp_sensortree *st =
0975 (struct smu_sdbp_sensortree *)&hdr[1];
0976 pm121_mach_model = st->model_id;
0977 }
0978
0979 pm121_connection = &pm121_connections[pm121_mach_model - 2];
0980
0981 printk(KERN_INFO "pm121: Initializing for iMac G5 iSight model ID %d\n",
0982 pm121_mach_model);
0983
0984 return 0;
0985 }
0986
0987
0988 static int pm121_probe(struct platform_device *ddev)
0989 {
0990 wf_register_client(&pm121_events);
0991
0992 return 0;
0993 }
0994
0995 static int pm121_remove(struct platform_device *ddev)
0996 {
0997 wf_unregister_client(&pm121_events);
0998 return 0;
0999 }
1000
1001 static struct platform_driver pm121_driver = {
1002 .probe = pm121_probe,
1003 .remove = pm121_remove,
1004 .driver = {
1005 .name = "windfarm",
1006 .bus = &platform_bus_type,
1007 },
1008 };
1009
1010
1011 static int __init pm121_init(void)
1012 {
1013 int rc = -ENODEV;
1014
1015 if (of_machine_is_compatible("PowerMac12,1"))
1016 rc = pm121_init_pm();
1017
1018 if (rc == 0) {
1019 request_module("windfarm_smu_controls");
1020 request_module("windfarm_smu_sensors");
1021 request_module("windfarm_smu_sat");
1022 request_module("windfarm_lm75_sensor");
1023 request_module("windfarm_max6690_sensor");
1024 request_module("windfarm_cpufreq_clamp");
1025 platform_driver_register(&pm121_driver);
1026 }
1027
1028 return rc;
1029 }
1030
1031 static void __exit pm121_exit(void)
1032 {
1033
1034 platform_driver_unregister(&pm121_driver);
1035 }
1036
1037
1038 module_init(pm121_init);
1039 module_exit(pm121_exit);
1040
1041 MODULE_AUTHOR("Étienne Bersac <bersace@gmail.com>");
1042 MODULE_DESCRIPTION("Thermal control logic for iMac G5 (iSight)");
1043 MODULE_LICENSE("GPL");
1044