Ejemplo n.º 1
0
/**
 * of_devfreq_cooling_register_power() - Register devfreq cooling device,
 *                                      with OF and power information.
 * @np:	Pointer to OF device_node.
 * @df:	Pointer to devfreq device.
 * @dfc_power:	Pointer to devfreq_cooling_power.
 *
 * Register a devfreq cooling device.  The available OPPs must be
 * registered on the device.
 *
 * If @dfc_power is provided, the cooling device is registered with the
 * power extensions.  For the power extensions to work correctly,
 * devfreq should use the simple_ondemand governor, other governors
 * are not currently supported.
 */
struct thermal_cooling_device *
of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,
				  struct devfreq_cooling_power *dfc_power)
{
	struct thermal_cooling_device *cdev;
	struct devfreq_cooling_device *dfc;
	char dev_name[THERMAL_NAME_LENGTH];
	int err;

	dfc = kzalloc(sizeof(*dfc), GFP_KERNEL);
	if (!dfc)
		return ERR_PTR(-ENOMEM);

	dfc->devfreq = df;

	if (dfc_power) {
		dfc->power_ops = dfc_power;

		devfreq_cooling_ops.get_requested_power =
			devfreq_cooling_get_requested_power;
		devfreq_cooling_ops.state2power = devfreq_cooling_state2power;
		devfreq_cooling_ops.power2state = devfreq_cooling_power2state;
	}

	err = devfreq_cooling_gen_tables(dfc);
	if (err)
		goto free_dfc;

	err = ida_simple_get(&devfreq_ida, 0, 0, GFP_KERNEL);
	if (err < 0)
		goto free_tables;
	dfc->id = err;

	snprintf(dev_name, sizeof(dev_name), "thermal-devfreq-%d", dfc->id);

	cdev = thermal_of_cooling_device_register(np, dev_name, dfc,
						  &devfreq_cooling_ops);
	if (IS_ERR(cdev)) {
		err = PTR_ERR(cdev);
		dev_err(df->dev.parent,
			"Failed to register devfreq cooling device (%d)\n",
			err);
		goto release_ida;
	}

	dfc->cdev = cdev;

	return cdev;

release_ida:
	ida_simple_remove(&devfreq_ida, dfc->id);
free_tables:
	kfree(dfc->power_table);
	kfree(dfc->freq_table);
free_dfc:
	kfree(dfc);

	return ERR_PTR(err);
}
Ejemplo n.º 2
0
/**
 * __isp_cooling_register - helper function to create isp cooling device
 * @np: a valid struct device_node to the cooling device device tree node
 * @clip_isp: ispmask of isp where the fps constraints will happen.
 *
 * This interface function registers the isp cooling device with the name
 * "thermal-isp-%x". This api can support multiple instances of isp
 * cooling devices. It also gives the opportunity to link the cooling device
 * with a device tree node, in order to bind it via the thermal DT code.
 *
 * Return: a valid struct thermal_cooling_device pointer on success,
 * on failure, it returns a corresponding ERR_PTR().
 */
static struct thermal_cooling_device *
__isp_cooling_register(struct device_node *np,
			   const struct cpumask *clip_isp)
{
	struct thermal_cooling_device *cool_dev;
	struct isp_cooling_device *isp_dev = NULL;
	char dev_name[THERMAL_NAME_LENGTH];
	int ret = 0;

	isp_dev = kzalloc(sizeof(struct isp_cooling_device),
			      GFP_KERNEL);
	if (!isp_dev)
		return ERR_PTR(-ENOMEM);

	ret = get_idr(&isp_idr, &isp_dev->id);
	if (ret) {
		kfree(isp_dev);
		return ERR_PTR(-EINVAL);
	}

	snprintf(dev_name, sizeof(dev_name), "thermal-isp-%d",
		 isp_dev->id);

	cool_dev = thermal_of_cooling_device_register(np, dev_name, isp_dev,
						      &isp_cooling_ops);
	if (IS_ERR(cool_dev)) {
		release_idr(&isp_idr, isp_dev->id);
		kfree(isp_dev);
		return cool_dev;
	}
	isp_dev->cool_dev = cool_dev;
	isp_dev->isp_state = 0;
	mutex_lock(&cooling_isp_lock);

	isp_dev_count++;

	mutex_unlock(&cooling_isp_lock);

	return cool_dev;
}
Ejemplo n.º 3
0
/**
 * __cpufreq_cooling_register - helper function to create cpufreq cooling device
 * @np: a valid struct device_node to the cooling device device tree node
 * @clip_cpus: cpumask of cpus where the frequency constraints will happen.
 *
 * This interface function registers the cpufreq cooling device with the name
 * "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
 * cooling devices. It also gives the opportunity to link the cooling device
 * with a device tree node, in order to bind it via the thermal DT code.
 *
 * Return: a valid struct thermal_cooling_device pointer on success,
 * on failure, it returns a corresponding ERR_PTR().
 */
static struct thermal_cooling_device *
__cpufreq_cooling_register(struct device_node *np,
                           const struct cpumask *clip_cpus)
{
    struct thermal_cooling_device *cool_dev;
    struct cpufreq_cooling_device *cpufreq_dev = NULL;
    unsigned int min = 0, max = 0;
    char dev_name[THERMAL_NAME_LENGTH];
    int ret = 0, i;
    struct cpufreq_policy policy;

    /* Verify that all the clip cpus have same freq_min, freq_max limit */
    for_each_cpu(i, clip_cpus) {
        /* continue if cpufreq policy not found and not return error */
        if (!cpufreq_get_policy(&policy, i))
            continue;
        if (min == 0 && max == 0) {
            min = policy.cpuinfo.min_freq;
            max = policy.cpuinfo.max_freq;
        } else {
            if (min != policy.cpuinfo.min_freq ||
                    max != policy.cpuinfo.max_freq)
                return ERR_PTR(-EINVAL);
        }
    }
    cpufreq_dev = kzalloc(sizeof(struct cpufreq_cooling_device),
                          GFP_KERNEL);
    if (!cpufreq_dev)
        return ERR_PTR(-ENOMEM);

    cpumask_copy(&cpufreq_dev->allowed_cpus, clip_cpus);

    ret = get_idr(&cpufreq_idr, &cpufreq_dev->id);
    if (ret) {
        kfree(cpufreq_dev);
        return ERR_PTR(-EINVAL);
    }

    snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d",
             cpufreq_dev->id);

    cool_dev = thermal_of_cooling_device_register(np, dev_name, cpufreq_dev,
               &cpufreq_cooling_ops);
    if (IS_ERR(cool_dev)) {
        release_idr(&cpufreq_idr, cpufreq_dev->id);
        kfree(cpufreq_dev);
        return ERR_PTR(-EINVAL);
    }
    cpufreq_dev->cool_dev = cool_dev;
    cpufreq_dev->cpufreq_state = 0;
    mutex_lock(&cooling_cpufreq_lock);

    /* Register the notifier for first cpufreq cooling device */
    if (cpufreq_dev_count == 0)
        cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
                                  CPUFREQ_POLICY_NOTIFIER);
    cpufreq_dev_count++;

    mutex_unlock(&cooling_cpufreq_lock);

    return cool_dev;
}