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; }
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; }