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