/* Implementation... */ static int create_cpu_loop(int cpu) { int chip = cpu / 2; int core = cpu & 1; struct smu_sdbp_header *hdr; struct smu_sdbp_cpupiddata *piddata; struct wf_cpu_pid_param pid; struct wf_control *main_fan = cpu_fans[0]; s32 tmax; int fmin; /* Get PID params from the appropriate SAT */ hdr = smu_sat_get_sdb_partition(chip, 0xC8 + core, NULL); if (hdr == NULL) { ; return -EINVAL; } piddata = (struct smu_sdbp_cpupiddata *)&hdr[1]; /* Get FVT params to get Tmax; if not found, assume default */ hdr = smu_sat_get_sdb_partition(chip, 0xC4 + core, NULL); if (hdr) { struct smu_sdbp_fvt *fvt = (struct smu_sdbp_fvt *)&hdr[1]; tmax = fvt->maxtemp << 16; } else tmax = 95 << 16; /* default to 95 degrees C */ /* We keep a global tmax for overtemp calculations */ if (tmax < cpu_all_tmax) cpu_all_tmax = tmax; /* * Darwin has a minimum fan speed of 1000 rpm for the 4-way and * 515 for the 2-way. That appears to be overkill, so for now, * impose a minimum of 750 or 515. */ fmin = (nr_cores > 2) ? 750 : 515; /* Initialize PID loop */ pid.interval = 1; /* seconds */ pid.history_len = piddata->history_len; pid.gd = piddata->gd; pid.gp = piddata->gp; pid.gr = piddata->gr / piddata->history_len; pid.pmaxadj = (piddata->max_power << 16) - (piddata->power_adj << 8); pid.ttarget = tmax - (piddata->target_temp_delta << 16); pid.tmax = tmax; pid.min = main_fan->ops->get_min(main_fan); pid.max = main_fan->ops->get_max(main_fan); if (pid.min < fmin) pid.min = fmin; wf_cpu_pid_init(&cpu_pid[cpu], &pid); return 0; }
/* Implementation... */ static int cpu_setup_pid(int cpu) { struct wf_cpu_pid_param pid; const struct mpu_data *mpu = cpu_mpu_data[cpu]; s32 tmax, ttarget, ptarget; int fmin, fmax, hsize; /* Get PID params from the appropriate MPU EEPROM */ tmax = mpu->tmax << 16; ttarget = mpu->ttarget << 16; ptarget = ((s32)(mpu->pmaxh - mpu->padjmax)) << 16; DBG("wf_72: CPU%d ttarget = %d.%03d, tmax = %d.%03d\n", cpu, FIX32TOPRINT(ttarget), FIX32TOPRINT(tmax)); /* We keep a global tmax for overtemp calculations */ if (tmax < cpu_all_tmax) cpu_all_tmax = tmax; /* Set PID min/max by using the rear fan min/max */ fmin = wf_control_get_min(cpu_fans[cpu][0]); fmax = wf_control_get_max(cpu_fans[cpu][0]); DBG("wf_72: CPU%d max RPM range = [%d..%d]\n", cpu, fmin, fmax); /* History size */ hsize = min_t(int, mpu->tguardband, WF_PID_MAX_HISTORY); DBG("wf_72: CPU%d history size = %d\n", cpu, hsize); /* Initialize PID loop */ pid.interval = 1; /* seconds */ pid.history_len = hsize; pid.gd = mpu->pid_gd; pid.gp = mpu->pid_gp; pid.gr = mpu->pid_gr; pid.tmax = tmax; pid.ttarget = ttarget; pid.pmaxadj = ptarget; pid.min = fmin; pid.max = fmax; wf_cpu_pid_init(&cpu_pid[cpu], &pid); cpu_pid[cpu].target = 4000; return 0; }
static void wf_smu_create_cpu_fans(void) { struct wf_cpu_pid_param pid_param; const struct smu_sdbp_header *hdr; struct smu_sdbp_cpupiddata *piddata; struct smu_sdbp_fvt *fvt; s32 tmax, tdelta, maxpow, powadj; /* First, locate the PID params in SMU SBD */ hdr = smu_get_sdb_partition(SMU_SDB_CPUPIDDATA_ID, NULL); if (hdr == 0) { printk(KERN_WARNING "windfarm: CPU PID fan config not found " "max fan speed\n"); goto fail; } piddata = (struct smu_sdbp_cpupiddata *)&hdr[1]; /* Get the FVT params for operating point 0 (the only supported one * for now) in order to get tmax */ hdr = smu_get_sdb_partition(SMU_SDB_FVT_ID, NULL); if (hdr) { fvt = (struct smu_sdbp_fvt *)&hdr[1]; tmax = ((s32)fvt->maxtemp) << 16; } else tmax = 0x5e0000; /* 94 degree default */ /* Alloc & initialize state */ wf_smu_cpu_fans = kmalloc(sizeof(struct wf_smu_cpu_fans_state), GFP_KERNEL); if (wf_smu_cpu_fans == NULL) goto fail; wf_smu_cpu_fans->ticks = 1; /* Fill PID params */ pid_param.interval = WF_SMU_CPU_FANS_INTERVAL; pid_param.history_len = piddata->history_len; if (pid_param.history_len > WF_CPU_PID_MAX_HISTORY) { printk(KERN_WARNING "windfarm: History size overflow on " "CPU control loop (%d)\n", piddata->history_len); pid_param.history_len = WF_CPU_PID_MAX_HISTORY; } pid_param.gd = piddata->gd; pid_param.gp = piddata->gp; pid_param.gr = piddata->gr / pid_param.history_len; tdelta = ((s32)piddata->target_temp_delta) << 16; maxpow = ((s32)piddata->max_power) << 16; powadj = ((s32)piddata->power_adj) << 16; pid_param.tmax = tmax; pid_param.ttarget = tmax - tdelta; pid_param.pmaxadj = maxpow - powadj; pid_param.min = fan_cpu_main->ops->get_min(fan_cpu_main); pid_param.max = fan_cpu_main->ops->get_max(fan_cpu_main); wf_cpu_pid_init(&wf_smu_cpu_fans->pid, &pid_param); DBG("wf: CPU Fan control initialized.\n"); DBG(" ttarged=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM\n", FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax), pid_param.min, pid_param.max); return; fail: printk(KERN_WARNING "windfarm: CPU fan config not found\n" "for this machine model, max fan speed\n"); if (cpufreq_clamp) wf_control_set_max(cpufreq_clamp); if (fan_cpu_main) wf_control_set_max(fan_cpu_main); }