From 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 13 May 2024 10:30:14 +0000 Subject: [PATCH] modify sin led gpio --- kernel/drivers/thermal/imx_thermal.c | 293 +++++++++++++++++++++++++++++++--------------------------- 1 files changed, 156 insertions(+), 137 deletions(-) diff --git a/kernel/drivers/thermal/imx_thermal.c b/kernel/drivers/thermal/imx_thermal.c index aa452ac..1666337 100644 --- a/kernel/drivers/thermal/imx_thermal.c +++ b/kernel/drivers/thermal/imx_thermal.c @@ -3,25 +3,19 @@ // Copyright 2013 Freescale Semiconductor, Inc. #include <linux/clk.h> -#include <linux/cpu.h> #include <linux/cpufreq.h> #include <linux/cpu_cooling.h> #include <linux/delay.h> -#include <linux/device.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> -#include <linux/kernel.h> #include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> -#include <linux/platform_device.h> #include <linux/regmap.h> -#include <linux/slab.h> #include <linux/thermal.h> -#include <linux/types.h> #include <linux/nvmem-consumer.h> +#include <linux/pm_runtime.h> #define REG_SET 0x4 #define REG_CLR 0x8 @@ -201,10 +195,10 @@ }; struct imx_thermal_data { + struct device *dev; struct cpufreq_policy *policy; struct thermal_zone_device *tz; struct thermal_cooling_device *cdev; - enum thermal_device_mode mode; struct regmap *tempmon; u32 c1, c2; /* See formula in imx_init_calib() */ int temp_passive; @@ -260,42 +254,14 @@ const struct thermal_soc_data *soc_data = data->socdata; struct regmap *map = data->tempmon; unsigned int n_meas; - bool wait; u32 val; + int ret; - if (data->mode == THERMAL_DEVICE_ENABLED) { - /* Check if a measurement is currently in progress */ - regmap_read(map, soc_data->temp_data, &val); - wait = !(val & soc_data->temp_valid_mask); - } else { - /* - * Every time we measure the temperature, we will power on the - * temperature sensor, enable measurements, take a reading, - * disable measurements, power off the temperature sensor. - */ - regmap_write(map, soc_data->sensor_ctrl + REG_CLR, - soc_data->power_down_mask); - regmap_write(map, soc_data->sensor_ctrl + REG_SET, - soc_data->measure_temp_mask); - - wait = true; - } - - /* - * According to the temp sensor designers, it may require up to ~17us - * to complete a measurement. - */ - if (wait) - usleep_range(20, 50); + ret = pm_runtime_resume_and_get(data->dev); + if (ret < 0) + return ret; regmap_read(map, soc_data->temp_data, &val); - - if (data->mode != THERMAL_DEVICE_ENABLED) { - regmap_write(map, soc_data->sensor_ctrl + REG_CLR, - soc_data->measure_temp_mask); - regmap_write(map, soc_data->sensor_ctrl + REG_SET, - soc_data->power_down_mask); - } if ((val & soc_data->temp_valid_mask) == 0) { dev_dbg(&tz->device, "temp measurement never finished\n"); @@ -335,56 +301,31 @@ enable_irq(data->irq); } - return 0; -} - -static int imx_get_mode(struct thermal_zone_device *tz, - enum thermal_device_mode *mode) -{ - struct imx_thermal_data *data = tz->devdata; - - *mode = data->mode; + pm_runtime_put(data->dev); return 0; } -static int imx_set_mode(struct thermal_zone_device *tz, - enum thermal_device_mode mode) +static int imx_change_mode(struct thermal_zone_device *tz, + enum thermal_device_mode mode) { struct imx_thermal_data *data = tz->devdata; - struct regmap *map = data->tempmon; - const struct thermal_soc_data *soc_data = data->socdata; if (mode == THERMAL_DEVICE_ENABLED) { - tz->polling_delay = IMX_POLLING_DELAY; - tz->passive_delay = IMX_PASSIVE_DELAY; - - regmap_write(map, soc_data->sensor_ctrl + REG_CLR, - soc_data->power_down_mask); - regmap_write(map, soc_data->sensor_ctrl + REG_SET, - soc_data->measure_temp_mask); + pm_runtime_get(data->dev); if (!data->irq_enabled) { data->irq_enabled = true; enable_irq(data->irq); } } else { - regmap_write(map, soc_data->sensor_ctrl + REG_CLR, - soc_data->measure_temp_mask); - regmap_write(map, soc_data->sensor_ctrl + REG_SET, - soc_data->power_down_mask); - - tz->polling_delay = 0; - tz->passive_delay = 0; + pm_runtime_put(data->dev); if (data->irq_enabled) { disable_irq(data->irq); data->irq_enabled = false; } } - - data->mode = mode; - thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); return 0; } @@ -419,6 +360,11 @@ int temp) { struct imx_thermal_data *data = tz->devdata; + int ret; + + ret = pm_runtime_resume_and_get(data->dev); + if (ret < 0) + return ret; /* do not allow changing critical threshold */ if (trip == IMX_TRIP_CRITICAL) @@ -431,6 +377,8 @@ data->temp_passive = temp; imx_set_alarm_temp(data, temp); + + pm_runtime_put(data->dev); return 0; } @@ -474,8 +422,7 @@ .bind = imx_bind, .unbind = imx_unbind, .get_temp = imx_get_temp, - .get_mode = imx_get_mode, - .set_mode = imx_set_mode, + .change_mode = imx_change_mode, .get_trip_type = imx_get_trip_type, .get_trip_temp = imx_get_trip_temp, .get_crit_temp = imx_get_crit_temp, @@ -648,26 +595,54 @@ }; MODULE_DEVICE_TABLE(of, of_imx_thermal_match); +#ifdef CONFIG_CPU_FREQ /* * Create cooling device in case no #cooling-cells property is available in * CPU node */ static int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data) { - struct device_node *np = of_get_cpu_node(data->policy->cpu, NULL); - int ret; + struct device_node *np; + int ret = 0; + + data->policy = cpufreq_cpu_get(0); + if (!data->policy) { + pr_debug("%s: CPUFreq policy not found\n", __func__); + return -EPROBE_DEFER; + } + + np = of_get_cpu_node(data->policy->cpu, NULL); if (!np || !of_find_property(np, "#cooling-cells", NULL)) { data->cdev = cpufreq_cooling_register(data->policy); if (IS_ERR(data->cdev)) { ret = PTR_ERR(data->cdev); cpufreq_cpu_put(data->policy); - return ret; } } + of_node_put(np); + + return ret; +} + +static void imx_thermal_unregister_legacy_cooling(struct imx_thermal_data *data) +{ + cpufreq_cooling_unregister(data->cdev); + cpufreq_cpu_put(data->policy); +} + +#else + +static inline int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data) +{ return 0; } + +static inline void imx_thermal_unregister_legacy_cooling(struct imx_thermal_data *data) +{ +} +#endif static int imx_thermal_probe(struct platform_device *pdev) { @@ -679,6 +654,8 @@ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; + + data->dev = &pdev->dev; map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon"); if (IS_ERR(map)) { @@ -715,17 +692,13 @@ if (of_find_property(pdev->dev.of_node, "nvmem-cells", NULL)) { ret = imx_init_from_nvmem_cells(pdev); - if (ret == -EPROBE_DEFER) - return ret; - if (ret) { - dev_err(&pdev->dev, "failed to init from nvmem: %d\n", - ret); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to init from nvmem\n"); } else { ret = imx_init_from_tempmon_data(pdev); if (ret) { - dev_err(&pdev->dev, "failed to init from from fsl,tempmon-data\n"); + dev_err(&pdev->dev, "failed to init from fsl,tempmon-data\n"); return ret; } } @@ -743,18 +716,10 @@ regmap_write(map, data->socdata->sensor_ctrl + REG_SET, data->socdata->power_down_mask); - data->policy = cpufreq_cpu_get(0); - if (!data->policy) { - pr_debug("%s: CPUFreq policy not found\n", __func__); - return -EPROBE_DEFER; - } - ret = imx_thermal_register_legacy_cooling(data); - if (ret) { - dev_err(&pdev->dev, - "failed to register cpufreq cooling device: %d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to register cpufreq cooling device\n"); data->thermal_clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(data->thermal_clk)) { @@ -762,9 +727,7 @@ if (ret != -EPROBE_DEFER) dev_err(&pdev->dev, "failed to get thermal clk: %d\n", ret); - cpufreq_cooling_unregister(data->cdev); - cpufreq_cpu_put(data->policy); - return ret; + goto legacy_cleanup; } /* @@ -777,9 +740,7 @@ ret = clk_prepare_enable(data->thermal_clk); if (ret) { dev_err(&pdev->dev, "failed to enable thermal clk: %d\n", ret); - cpufreq_cooling_unregister(data->cdev); - cpufreq_cpu_put(data->policy); - return ret; + goto legacy_cleanup; } data->tz = thermal_zone_device_register("imx_thermal_zone", @@ -792,10 +753,7 @@ ret = PTR_ERR(data->tz); dev_err(&pdev->dev, "failed to register thermal zone device %d\n", ret); - clk_disable_unprepare(data->thermal_clk); - cpufreq_cooling_unregister(data->cdev); - cpufreq_cpu_put(data->policy); - return ret; + goto clk_disable; } dev_info(&pdev->dev, "%s CPU temperature grade - max:%dC" @@ -818,87 +776,148 @@ data->socdata->power_down_mask); regmap_write(map, data->socdata->sensor_ctrl + REG_SET, data->socdata->measure_temp_mask); + /* After power up, we need a delay before first access can be done. */ + usleep_range(20, 50); + + /* the core was configured and enabled just before */ + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(data->dev); + + ret = pm_runtime_resume_and_get(data->dev); + if (ret < 0) + goto disable_runtime_pm; data->irq_enabled = true; - data->mode = THERMAL_DEVICE_ENABLED; + ret = thermal_zone_device_enable(data->tz); + if (ret) + goto thermal_zone_unregister; 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); - clk_disable_unprepare(data->thermal_clk); - thermal_zone_device_unregister(data->tz); - cpufreq_cooling_unregister(data->cdev); - cpufreq_cpu_put(data->policy); - return ret; + goto thermal_zone_unregister; } + pm_runtime_put(data->dev); + return 0; + +thermal_zone_unregister: + thermal_zone_device_unregister(data->tz); +disable_runtime_pm: + pm_runtime_put_noidle(data->dev); + pm_runtime_disable(data->dev); +clk_disable: + clk_disable_unprepare(data->thermal_clk); +legacy_cleanup: + imx_thermal_unregister_legacy_cooling(data); + + return ret; } static int imx_thermal_remove(struct platform_device *pdev) { struct imx_thermal_data *data = platform_get_drvdata(pdev); - struct regmap *map = data->tempmon; - /* Disable measurements */ - regmap_write(map, data->socdata->sensor_ctrl + REG_SET, - data->socdata->power_down_mask); - if (!IS_ERR(data->thermal_clk)) - clk_disable_unprepare(data->thermal_clk); + pm_runtime_put_noidle(data->dev); + pm_runtime_disable(data->dev); thermal_zone_device_unregister(data->tz); - cpufreq_cooling_unregister(data->cdev); - cpufreq_cpu_put(data->policy); + imx_thermal_unregister_legacy_cooling(data); return 0; } -#ifdef CONFIG_PM_SLEEP -static int imx_thermal_suspend(struct device *dev) +static int __maybe_unused imx_thermal_suspend(struct device *dev) { struct imx_thermal_data *data = dev_get_drvdata(dev); - struct regmap *map = data->tempmon; + int ret; /* * Need to disable thermal sensor, otherwise, when thermal core * try to get temperature before thermal sensor resume, a wrong * temperature will be read as the thermal sensor is powered - * down. + * down. This is done in change_mode() operation called from + * thermal_zone_device_disable() */ - regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, - data->socdata->measure_temp_mask); - regmap_write(map, data->socdata->sensor_ctrl + REG_SET, - data->socdata->power_down_mask); - data->mode = THERMAL_DEVICE_DISABLED; + ret = thermal_zone_device_disable(data->tz); + if (ret) + return ret; + + return pm_runtime_force_suspend(data->dev); +} + +static int __maybe_unused imx_thermal_resume(struct device *dev) +{ + struct imx_thermal_data *data = dev_get_drvdata(dev); + int ret; + + ret = pm_runtime_force_resume(data->dev); + if (ret) + return ret; + /* Enabled thermal sensor after resume */ + return thermal_zone_device_enable(data->tz); +} + +static int __maybe_unused imx_thermal_runtime_suspend(struct device *dev) +{ + struct imx_thermal_data *data = dev_get_drvdata(dev); + const struct thermal_soc_data *socdata = data->socdata; + struct regmap *map = data->tempmon; + int ret; + + ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR, + socdata->measure_temp_mask); + if (ret) + return ret; + + ret = regmap_write(map, socdata->sensor_ctrl + REG_SET, + socdata->power_down_mask); + if (ret) + return ret; + clk_disable_unprepare(data->thermal_clk); return 0; } -static int imx_thermal_resume(struct device *dev) +static int __maybe_unused imx_thermal_runtime_resume(struct device *dev) { struct imx_thermal_data *data = dev_get_drvdata(dev); + const struct thermal_soc_data *socdata = data->socdata; struct regmap *map = data->tempmon; int ret; ret = clk_prepare_enable(data->thermal_clk); if (ret) return ret; - /* Enabled thermal sensor after resume */ - regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, - data->socdata->power_down_mask); - regmap_write(map, data->socdata->sensor_ctrl + REG_SET, - data->socdata->measure_temp_mask); - data->mode = THERMAL_DEVICE_ENABLED; + + ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR, + socdata->power_down_mask); + if (ret) + return ret; + + ret = regmap_write(map, socdata->sensor_ctrl + REG_SET, + socdata->measure_temp_mask); + if (ret) + return ret; + + /* + * According to the temp sensor designers, it may require up to ~17us + * to complete a measurement. + */ + usleep_range(20, 50); return 0; } -#endif -static SIMPLE_DEV_PM_OPS(imx_thermal_pm_ops, - imx_thermal_suspend, imx_thermal_resume); +static const struct dev_pm_ops imx_thermal_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(imx_thermal_suspend, imx_thermal_resume) + SET_RUNTIME_PM_OPS(imx_thermal_runtime_suspend, + imx_thermal_runtime_resume, NULL) +}; static struct platform_driver imx_thermal = { .driver = { -- Gitblit v1.6.2