示例#1
0
static int nvhost_pod_init(struct devfreq *df)
{
	struct nvhost_device *d = to_nvhost_device(df->dev.parent);
	struct podgov_info_rec *podgov;
	ktime_t now = ktime_get();
	int error = 0;

	struct nvhost_devfreq_ext_stat *ext_stat;
	struct devfreq_dev_status dev_stat;
	int stat = 0;

	long rate;
	int freqs[MAX_FREQ_COUNT];

	podgov = kzalloc(sizeof(struct podgov_info_rec), GFP_KERNEL);
	if (!podgov)
		goto err_alloc_podgov;
	df->data = (void *)podgov;

	/* This should be removed after the governor include also the hint
	 * interface */
	local_podgov = podgov;

	/* Initialise workers */
	INIT_WORK(&podgov->work, podgov_clocks_handler);
	INIT_DELAYED_WORK(&podgov->idle_timer, podgov_idle_handler);

	/* Set scaling parameter defaults */
	podgov->enable = 1;
	podgov->p_adjust = 0;
	podgov->block = 0;
	podgov->p_use_throughput_hint = 1;
	podgov->idle_min = podgov->p_idle_min = 100;
	podgov->idle_max = podgov->p_idle_max = 150;
	podgov->p_hint_lo_limit = 800;
	podgov->p_hint_hi_limit = 1015;
	podgov->p_scaleup_limit = 1275;
	podgov->p_scaledown_limit = 1475;
	podgov->p_smooth = 7;
	
	podgov->p_estimation_window = 10000;
	podgov->adjustment_type = ADJUSTMENT_DEVICE_REQ;
	podgov->p_user = 0;

	/* Reset clock counters */
	podgov->last_throughput_hint = now;
	podgov->last_scale = now;
	podgov->last_adjust = now;
	podgov->last_estimation_window = now;
	podgov->estimation_window = now;
	podgov->last_notification = now;

	podgov->power_manager = df;

	/* Get the current status of the device */
	stat = df->profile->get_dev_status(df->dev.parent, &dev_stat);
	if (!dev_stat.private_data) {
		pr_err("podgov: device does not support ext_stat.\n");
		goto err_get_current_status;
	}
	ext_stat = dev_stat.private_data;
	df->previous_freq = dev_stat.current_frequency;
	df->min_freq = ext_stat->min_freq;
	df->max_freq = ext_stat->max_freq;

	podgov->p_freq_request = ext_stat->max_freq;

	/* Create sysfs entries for controlling this governor */
	error = device_create_file(&d->dev,
			&dev_attr_enable_3d_scaling);
	if (error)
		goto err_create_sysfs_entry;

	error = device_create_file(&d->dev,
			&dev_attr_user);
	if (error)
		goto err_create_sysfs_entry;

	error = device_create_file(&d->dev,
			&dev_attr_freq_request);
	if (error)
		goto err_create_sysfs_entry;

	rate = 0;
	podgov->freq_count = 0;
	while (rate <= df->max_freq) {
		long rounded_rate;
		if (unlikely(podgov->freq_count == MAX_FREQ_COUNT)) {
			pr_err("%s: too many frequencies\n", __func__);
			break;
		}
		rounded_rate = clk_round_rate(clk_get_parent(d->clk[0]), rate);
		if (podgov->freq_count &&
		    freqs[podgov->freq_count - 1] == rounded_rate)
			break;
		freqs[podgov->freq_count++] = rounded_rate;
		rate = rounded_rate + 2000;
	}

	podgov->freqlist =
		kmalloc(podgov->freq_count * sizeof(int), GFP_KERNEL);
	if (podgov->freqlist == NULL)
		goto err_allocate_freq_list;

	memcpy(podgov->freqlist, freqs,
		podgov->freq_count * sizeof(int));

	podgov->idle_avg = 0;
	podgov->hint_avg = 0;

	nvhost_scale3d_debug_init(df);

	return 0;

err_allocate_freq_list:
	device_remove_file(&d->dev, &dev_attr_enable_3d_scaling);
	device_remove_file(&d->dev, &dev_attr_user);
	device_remove_file(&d->dev, &dev_attr_freq_request);
err_create_sysfs_entry:
	dev_err(&df->dev, "failed to create sysfs attributes");
err_get_current_status:
	kfree(podgov);
err_alloc_podgov:
	return -ENOMEM;
}
示例#2
0
static int nvhost_pod_init(struct devfreq *df)
{
	struct podgov_info_rec *podgov;
	struct platform_device *d = to_platform_device(df->dev.parent);
	ktime_t now = ktime_get();
	enum tegra_chipid cid = tegra_get_chipid();
	int error = 0;

	struct nvhost_devfreq_ext_stat *ext_stat;
	struct devfreq_dev_status dev_stat;
	int stat = 0;

	podgov = kzalloc(sizeof(struct podgov_info_rec), GFP_KERNEL);
	if (!podgov)
		goto err_alloc_podgov;
	df->data = (void *)podgov;

	/* Initialise workers */
	INIT_DELAYED_WORK(&podgov->idle_timer, podgov_idle_handler);

	/* Set scaling parameter defaults */
	podgov->enable = 1;
	podgov->block = 0;
	podgov->p_use_throughput_hint = 1;

	if (!strcmp(d->name, "vic03")) {
		podgov->p_load_max = 990;
		podgov->p_load_target = 800;
		podgov->p_bias = 80;
		podgov->p_hint_lo_limit = 500;
		podgov->p_hint_hi_limit = 997;
		podgov->p_scaleup_limit = 1100;
		podgov->p_scaledown_limit = 1300;
		podgov->p_smooth = 10;
		podgov->p_damp = 7;
	} else {
		switch (cid) {
		case TEGRA_CHIPID_TEGRA14:
		case TEGRA_CHIPID_TEGRA11:
		case TEGRA_CHIPID_TEGRA12:
			podgov->p_load_max = 900;
			podgov->p_load_target = 700;
			podgov->p_bias = 80;
			podgov->p_hint_lo_limit = 500;
			podgov->p_hint_hi_limit = 997;
			podgov->p_scaleup_limit = 1100;
			podgov->p_scaledown_limit = 1300;
			podgov->p_smooth = 10;
			podgov->p_damp = 7;
			break;
		default:
			pr_err("%s: un-supported chip id\n", __func__);
			goto err_unsupported_chip_id;
			break;
		}
	}

	podgov->p_slowdown_delay = 10;
	podgov->p_block_window = 50000;
	podgov->adjustment_type = ADJUSTMENT_DEVICE_REQ;
	podgov->p_user = 0;

	/* Reset clock counters */
	podgov->last_throughput_hint = now;
	podgov->last_scale = now;

	podgov->power_manager = df;

	/* Get the current status of the device */
	stat = df->profile->get_dev_status(df->dev.parent, &dev_stat);
	if (!dev_stat.private_data) {
		pr_err("podgov: device does not support ext_stat.\n");
		goto err_get_current_status;
	}
	ext_stat = dev_stat.private_data;

	/* store the limits */
	df->min_freq = ext_stat->min_freq;
	df->max_freq = ext_stat->max_freq;

	podgov->p_freq_request = ext_stat->max_freq;

	/* Create sysfs entries for controlling this governor */
	error = device_create_file(&d->dev,
			&dev_attr_enable_3d_scaling);
	if (error)
		goto err_create_sysfs_entry;

	error = device_create_file(&d->dev,
			&dev_attr_user);
	if (error)
		goto err_create_sysfs_entry;

	error = device_create_file(&d->dev,
			&dev_attr_freq_request);
	if (error)
		goto err_create_sysfs_entry;

	podgov->freq_count = df->profile->max_state;
	podgov->freqlist = df->profile->freq_table;
	if (!podgov->freq_count || !podgov->freqlist)
		goto err_get_freqs;

	podgov->idle_avg = 0;
	podgov->freq_avg = 0;
	podgov->hint_avg = 0;

	nvhost_scale3d_debug_init(df);

	/* register the governor to throughput hint notifier chain */
	podgov->throughput_hint_notifier.notifier_call =
		&nvhost_scale3d_set_throughput_hint;
	blocking_notifier_chain_register(&throughput_notifier_list,
					 &podgov->throughput_hint_notifier);

	return 0;

err_get_freqs:
	device_remove_file(&d->dev, &dev_attr_enable_3d_scaling);
	device_remove_file(&d->dev, &dev_attr_user);
	device_remove_file(&d->dev, &dev_attr_freq_request);
err_create_sysfs_entry:
	dev_err(&d->dev, "failed to create sysfs attributes");
err_get_current_status:
err_unsupported_chip_id:
	kfree(podgov);
err_alloc_podgov:
	return -ENOMEM;
}