Пример #1
0
/* 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;
}
Пример #2
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);
}