Пример #1
0
static int imx_thermal_probe(struct platform_device *pdev)
{
	struct imx_thermal_data *data;
	struct cpumask clip_cpus;
	struct regmap *map;
	int measure_freq;
	int ret;

	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon");
	if (IS_ERR(map)) {
		ret = PTR_ERR(map);
		dev_err(&pdev->dev, "failed to get tempmon regmap: %d\n", ret);
		return ret;
	}
	data->tempmon = map;

	data->irq = platform_get_irq(pdev, 0);
	if (data->irq < 0)
		return data->irq;

	ret = devm_request_threaded_irq(&pdev->dev, data->irq,
			imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
			0, "imx_thermal", data);
	if (ret < 0) {
		dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);
		return ret;
	}

	platform_set_drvdata(pdev, data);

	ret = imx_get_sensor_data(pdev);
	if (ret) {
		dev_err(&pdev->dev, "failed to get sensor data\n");
		return ret;
	}

	/* Make sure sensor is in known good state for measurements */
	regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
	regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
	regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
	regmap_write(map, MISC0 + REG_SET, MISC0_REFTOP_SELBIASOFF);
	regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);

	cpumask_set_cpu(0, &clip_cpus);
	data->cdev = cpufreq_cooling_register(&clip_cpus);
	if (IS_ERR(data->cdev)) {
		ret = PTR_ERR(data->cdev);
		dev_err(&pdev->dev,
			"failed to register cpufreq cooling device: %d\n", ret);
		return ret;
	}

	data->tz = thermal_zone_device_register("imx_thermal_zone",
						IMX_TRIP_NUM,
						BIT(IMX_TRIP_PASSIVE), data,
						&imx_tz_ops, NULL,
						IMX_PASSIVE_DELAY,
						IMX_POLLING_DELAY);
	if (IS_ERR(data->tz)) {
		ret = PTR_ERR(data->tz);
		dev_err(&pdev->dev,
			"failed to register thermal zone device %d\n", ret);
		cpufreq_cooling_unregister(data->cdev);
		return ret;
	}

	/* Enable measurements at ~ 10 Hz */
	regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
	measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */
	regmap_write(map, TEMPSENSE1 + REG_SET, measure_freq);
	imx_set_alarm_temp(data, data->temp_passive);
	regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
	regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);

	data->irq_enabled = true;
	data->mode = THERMAL_DEVICE_ENABLED;

	return 0;
}
/* Register with the in-kernel thermal management */
static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
{
	int ret, count, tab_size, pos = 0;
	struct freq_clip_table *tab_ptr, *clip_data;
#ifdef CONFIG_ARM_EXYNOS_MP_CPUFREQ
	struct freq_clip_table *tab_ptr_kfc;
#endif

	if (!sensor_conf || !sensor_conf->read_temperature) {
		pr_err("Temperature sensor not initialised\n");
		return -EINVAL;
	}

	th_zone = kzalloc(sizeof(struct exynos_thermal_zone), GFP_KERNEL);
	if (!th_zone)
		return -ENOMEM;

	th_zone->sensor_conf = sensor_conf;

	tab_ptr = (struct freq_clip_table *)sensor_conf->cooling_data.freq_data;
#ifdef CONFIG_ARM_EXYNOS_MP_CPUFREQ
	tab_ptr_kfc = (struct freq_clip_table *)sensor_conf->cooling_data_kfc.freq_data;
#endif

	/* Register the cpufreq cooling device */
	for (count = 0; count < EXYNOS_ZONE_COUNT; count++) {
		tab_size = sensor_conf->cooling_data.size[count];
		if (tab_size == 0)
			continue;

		clip_data = (struct freq_clip_table *)&(tab_ptr[pos]);

#ifdef CONFIG_CPU_THERMAL
		th_zone->cool_dev[count] = cpufreq_cooling_register(
						clip_data, tab_size);
#endif

#ifdef CONFIG_ARM_EXYNOS_MP_CPUFREQ
		clip_data = (struct freq_clip_table *)&(tab_ptr_kfc[pos]);

#ifdef CONFIG_CPU_THERMAL
		th_zone->cool_dev_kfc[count] = cpufreq_cooling_register(
						clip_data, tab_size);
#endif
#endif
		pos += tab_size;

		if (IS_ERR(th_zone->cool_dev[count])) {
			pr_err("Failed to register cpufreq cooling device\n");
			ret = -EINVAL;
			th_zone->cool_dev_size = count;
			goto err_unregister;
		}
	}
	th_zone->cool_dev_size = count;

	th_zone->therm_dev = thermal_zone_device_register(sensor_conf->name,
			EXYNOS_ZONE_COUNT, 7, NULL, &exynos_dev_ops, 1, 1, PASSIVE_INTERVAL,
			IDLE_INTERVAL);

	if (IS_ERR(th_zone->therm_dev)) {
		pr_err("Failed to register thermal zone device\n");
		ret = -EINVAL;
		goto err_unregister;
	}
	th_zone->mode = THERMAL_DEVICE_ENABLED;

	pr_info("Exynos: Kernel Thermal management registered\n");

	return 0;

err_unregister:
	exynos_unregister_thermal();
	return ret;
}
static int __init kona_thermal_probe(struct platform_device *pdev)
{
	struct kona_tmon_thermal *thermal;
	struct kona_tmon_pdata	*pdata;
	int ret = 0;

	thermal = devm_kzalloc(&pdev->dev, sizeof(*thermal), GFP_KERNEL);
	if (!thermal)
		return -ENOMEM;

	if (pdev->dev.of_node) {
		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
		if (!pdata)
			return -ENOMEM;

		ret = kona_tmon_parse_dt(pdev, pdata);
		if (ret) {
			tmon_dbg(TMON_LOG_INIT, "error while parsing DT\n");
			return ret;
		}
	} else {
		pdata = pdev->dev.platform_data;
	}

	if (!pdata) {
		tmon_dbg(TMON_LOG_INIT, "platform data get failed\n");
		return -ENODEV;
	}
	thermal->pdata = pdata;

	ret = devm_request_irq(&pdev->dev, thermal->pdata->irq, kona_tmon_isr,
			IRQ_LEVEL | IRQF_NO_SUSPEND | IRQF_DISABLED,
			pdev->name, thermal);
	if (ret < 0) {
		tmon_dbg(TMON_LOG_INIT, "irq registration failed\n");
		return ret;
	}

	thermal->tmon_apb_clk = clk_get(NULL, pdata->tmon_apb_clk);
	if (IS_ERR(thermal->tmon_apb_clk)) {
		tmon_dbg(TMON_LOG_INIT, "tmon apb clk get failed\n");
		return PTR_ERR(thermal->tmon_apb_clk);
	}
	clk_enable(thermal->tmon_apb_clk);

	thermal->tmon_1m_clk = clk_get(NULL, pdata->tmon_1m_clk);
	if (IS_ERR(thermal->tmon_1m_clk)) {
		tmon_dbg(TMON_LOG_INIT, "tmon 1m clk get failed\n");
		return PTR_ERR(thermal->tmon_1m_clk);
	}

	if (clk_set_rate(thermal->tmon_1m_clk, TMON_1M_CLK_RATE)) {
		tmon_dbg(TMON_LOG_INIT, "tmon_1m_clk rate set failed\n");
		return -EINVAL;
	}
	clk_enable(thermal->tmon_1m_clk);

	mutex_init(&thermal->lock);
	INIT_WORK(&thermal->isr_work, kona_tmon_irq_work);
	INIT_DELAYED_WORK(&thermal->polling_work, kona_tmon_polling_work);
	platform_set_drvdata(pdev, thermal);

	thermal->active_cnt = kona_tmon_active_trip_cnt(thermal);
	ret = kona_tmon_init(thermal);
	if (ret) {
		tmon_dbg(TMON_LOG_INIT, "tmon configuration failed\n");
		goto err_init;
	}

	thermal->freq_cdev = cpufreq_cooling_register(cpu_present_mask);
	if (IS_ERR(thermal->freq_cdev)) {
		tmon_dbg(TMON_LOG_INIT, "cpufreq cooling dev registration failed\n");
		ret = PTR_ERR(thermal->freq_cdev);
		goto err_cpucool;
	}

	thermal->tz  = thermal_zone_device_register("tmon",
			thermal->pdata->trip_cnt, TRIP_UPDATE_MASK, thermal,
			&tmon_ops, NULL, 0, 0);
	if (IS_ERR(thermal->tz)) {
		tmon_dbg(TMON_LOG_INIT, "thermal zone registration failed\n");
		ret = PTR_ERR(thermal->tz);
		goto err_tz_reg;
	}

	suspend_poweroff = pdata->flags & TMON_SUSPEND_POWEROFF ?
			ENABLE_SUSPEND_POWEROFF : DISABLE_SUSPEND_POWEROFF;

	/* start polling only if cur_idx is greater than zero */
	if (thermal->cur_idx)
		schedule_delayed_work(&thermal->polling_work,
					msecs_to_jiffies(pdata->poll_rate_ms));

	if (kona_tmon_debugfs_init(thermal))
		tmon_dbg(TMON_LOG_DBG, "tmon debugfs init failed\n");

	return ret;

err_tz_reg:
	cpufreq_cooling_unregister(thermal->freq_cdev);
err_cpucool:
	kona_tmon_exit(thermal, false);
err_init:
	clk_disable(thermal->tmon_1m_clk);
	clk_disable(thermal->tmon_apb_clk);
	return ret;
}
Пример #4
0
static int imx_thermal_probe(struct platform_device *pdev)
{
	struct imx_thermal_data *data;
	struct cpumask clip_cpus;
	struct regmap *map;
	int measure_freq;
	int ret;

	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon");
	if (IS_ERR(map)) {
		ret = PTR_ERR(map);
		dev_err(&pdev->dev, "failed to get tempmon regmap: %d\n", ret);
		return ret;
	}
	data->tempmon = map;

	data->irq = platform_get_irq(pdev, 0);
	if (data->irq < 0)
		return data->irq;

	ret = devm_request_threaded_irq(&pdev->dev, data->irq,
			imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
			0, "imx_thermal", data);
	if (ret < 0) {
		dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);
		return ret;
	}

	platform_set_drvdata(pdev, data);

	ret = imx_get_sensor_data(pdev);
	if (ret) {
		dev_err(&pdev->dev, "failed to get sensor data\n");
		return ret;
	}

	/* Make sure sensor is in known good state for measurements */
	regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
	regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
	regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
	regmap_write(map, MISC0 + REG_SET, MISC0_REFTOP_SELBIASOFF);
	regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);

	cpumask_set_cpu(0, &clip_cpus);
	data->cdev = cpufreq_cooling_register(&clip_cpus);
	if (IS_ERR(data->cdev)) {
		ret = PTR_ERR(data->cdev);
		dev_err(&pdev->dev,
			"failed to register cpufreq cooling device: %d\n", ret);
		return ret;
	}

	data->tz = thermal_zone_device_register("imx_thermal_zone",
						IMX_TRIP_NUM,
						BIT(IMX_TRIP_PASSIVE), data,
						&imx_tz_ops, NULL,
						IMX_PASSIVE_DELAY,
						IMX_POLLING_DELAY);
	if (IS_ERR(data->tz)) {
		ret = PTR_ERR(data->tz);
		dev_err(&pdev->dev,
			"failed to register thermal zone device %d\n", ret);
		cpufreq_cooling_unregister(data->cdev);
		return ret;
	}

	data->thermal_clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(data->thermal_clk)) {
		dev_warn(&pdev->dev, "failed to get thermal clk!\n");
	} else {
		/*
		 * Thermal sensor needs clk on to get correct value, normally
		 * we should enable its clk before taking measurement and disable
		 * clk after measurement is done, but if alarm function is enabled,
		 * hardware will auto measure the temperature periodically, so we
		 * need to keep the clk always on for alarm function.
		 */
		ret = clk_prepare_enable(data->thermal_clk);
		if (ret)
			dev_warn(&pdev->dev, "failed to enable thermal clk: %d\n", ret);
	}

	/* Enable measurements at ~ 10 Hz */
	regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
	measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */
	regmap_write(map, TEMPSENSE1 + REG_SET, measure_freq);
	imx_set_alarm_temp(data, data->temp_passive);
	regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
	regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);

	data->irq_enabled = true;
	data->mode = THERMAL_DEVICE_ENABLED;

	return 0;
}
/* Register with the in-kernel thermal management */
int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
{
	int ret;
	struct cpumask mask_val;
	struct exynos_thermal_zone *th_zone;

	if (!sensor_conf || !sensor_conf->read_temperature) {
		pr_err("Temperature sensor not initialised\n");
		return -EINVAL;
	}

	th_zone = devm_kzalloc(sensor_conf->dev,
				sizeof(struct exynos_thermal_zone), GFP_KERNEL);
	if (!th_zone)
		return -ENOMEM;

	th_zone->sensor_conf = sensor_conf;
	/*
	 * TODO: 1) Handle multiple cooling devices in a thermal zone
	 *	 2) Add a flag/name in cooling info to map to specific
	 *	 sensor
	 */
	if (sensor_conf->cooling_data.freq_clip_count > 0) {
		cpumask_set_cpu(0, &mask_val);
		th_zone->cool_dev[th_zone->cool_dev_size] =
					cpufreq_cooling_register(&mask_val);
		if (IS_ERR(th_zone->cool_dev[th_zone->cool_dev_size])) {
			ret = PTR_ERR(th_zone->cool_dev[th_zone->cool_dev_size]);
			if (ret != -EPROBE_DEFER)
				dev_err(sensor_conf->dev,
					"Failed to register cpufreq cooling device: %d\n",
					ret);
			goto err_unregister;
		}
		th_zone->cool_dev_size++;
	}

	th_zone->therm_dev = thermal_zone_device_register(
			sensor_conf->name, sensor_conf->trip_data.trip_count,
			0, th_zone, &exynos_dev_ops, NULL, 0,
			sensor_conf->trip_data.trigger_falling ? 0 :
			IDLE_INTERVAL);

	if (IS_ERR(th_zone->therm_dev)) {
		dev_err(sensor_conf->dev,
			"Failed to register thermal zone device\n");
		ret = PTR_ERR(th_zone->therm_dev);
		goto err_unregister;
	}
	th_zone->mode = THERMAL_DEVICE_ENABLED;
	sensor_conf->pzone_data = th_zone;

	dev_info(sensor_conf->dev,
		"Exynos: Thermal zone(%s) registered\n", sensor_conf->name);

	return 0;

err_unregister:
	exynos_unregister_thermal(sensor_conf);
	return ret;
}