hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
kernel/drivers/thermal/ti-soc-thermal/ti-bandgap.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * TI Bandgap temperature sensor driver
34 *
....@@ -6,21 +7,6 @@
67 * Author: Moiz Sonasath <m-sonasath@ti.com>
78 * Couple of fixes, DT and MFD adaptation:
89 * Eduardo Valentin <eduardo.valentin@ti.com>
9
- *
10
- * This program is free software; you can redistribute it and/or
11
- * modify it under the terms of the GNU General Public License
12
- * version 2 as published by the Free Software Foundation.
13
- *
14
- * This program is distributed in the hope that it will be useful, but
15
- * WITHOUT ANY WARRANTY; without even the implied warranty of
16
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
- * General Public License for more details.
18
- *
19
- * You should have received a copy of the GNU General Public License
20
- * along with this program; if not, write to the Free Software
21
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22
- * 02110-1301 USA
23
- *
2410 */
2511
2612 #include <linux/module.h>
....@@ -29,21 +15,31 @@
2915 #include <linux/kernel.h>
3016 #include <linux/interrupt.h>
3117 #include <linux/clk.h>
32
-#include <linux/gpio.h>
18
+#include <linux/gpio/consumer.h>
3319 #include <linux/platform_device.h>
3420 #include <linux/err.h>
3521 #include <linux/types.h>
3622 #include <linux/spinlock.h>
23
+#include <linux/sys_soc.h>
3724 #include <linux/reboot.h>
3825 #include <linux/of_device.h>
3926 #include <linux/of_platform.h>
4027 #include <linux/of_irq.h>
41
-#include <linux/of_gpio.h>
4228 #include <linux/io.h>
29
+#include <linux/cpu_pm.h>
30
+#include <linux/device.h>
31
+#include <linux/pm_runtime.h>
32
+#include <linux/pm.h>
33
+#include <linux/of.h>
34
+#include <linux/of_device.h>
4335
4436 #include "ti-bandgap.h"
4537
4638 static int ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id);
39
+#ifdef CONFIG_PM_SLEEP
40
+static int bandgap_omap_cpu_notifier(struct notifier_block *nb,
41
+ unsigned long cmd, void *v);
42
+#endif
4743
4844 /*** Helper functions to access registers and their bitfields ***/
4945
....@@ -757,27 +753,13 @@
757753 static int ti_bandgap_tshut_init(struct ti_bandgap *bgp,
758754 struct platform_device *pdev)
759755 {
760
- int gpio_nr = bgp->tshut_gpio;
761756 int status;
762757
763
- /* Request for gpio_86 line */
764
- status = gpio_request(gpio_nr, "tshut");
765
- if (status < 0) {
766
- dev_err(bgp->dev, "Could not request for TSHUT GPIO:%i\n", 86);
767
- return status;
768
- }
769
- status = gpio_direction_input(gpio_nr);
770
- if (status) {
771
- dev_err(bgp->dev, "Cannot set input TSHUT GPIO %d\n", gpio_nr);
772
- return status;
773
- }
774
-
775
- status = request_irq(gpio_to_irq(gpio_nr), ti_bandgap_tshut_irq_handler,
758
+ status = request_irq(gpiod_to_irq(bgp->tshut_gpiod),
759
+ ti_bandgap_tshut_irq_handler,
776760 IRQF_TRIGGER_RISING, "tshut", NULL);
777
- if (status) {
778
- gpio_free(gpio_nr);
761
+ if (status)
779762 dev_err(bgp->dev, "request irq failed for TSHUT");
780
- }
781763
782764 return 0;
783765 }
....@@ -801,10 +783,9 @@
801783 int ret;
802784
803785 bgp->irq = platform_get_irq(pdev, 0);
804
- if (bgp->irq < 0) {
805
- dev_err(&pdev->dev, "get_irq failed\n");
786
+ if (bgp->irq < 0)
806787 return bgp->irq;
807
- }
788
+
808789 ret = request_threaded_irq(bgp->irq, NULL,
809790 ti_bandgap_talert_irq_handler,
810791 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
....@@ -874,16 +855,26 @@
874855 } while (res);
875856
876857 if (TI_BANDGAP_HAS(bgp, TSHUT)) {
877
- bgp->tshut_gpio = of_get_gpio(node, 0);
878
- if (!gpio_is_valid(bgp->tshut_gpio)) {
879
- dev_err(&pdev->dev, "invalid gpio for tshut (%d)\n",
880
- bgp->tshut_gpio);
881
- return ERR_PTR(-EINVAL);
858
+ bgp->tshut_gpiod = devm_gpiod_get(&pdev->dev, NULL, GPIOD_IN);
859
+ if (IS_ERR(bgp->tshut_gpiod)) {
860
+ dev_err(&pdev->dev, "invalid gpio for tshut\n");
861
+ return ERR_CAST(bgp->tshut_gpiod);
882862 }
883863 }
884864
885865 return bgp;
886866 }
867
+
868
+/*
869
+ * List of SoCs on which the CPU PM notifier can cause erros on the DTEMP
870
+ * readout.
871
+ * Enabled notifier on these machines results in erroneous, random values which
872
+ * could trigger unexpected thermal shutdown.
873
+ */
874
+static const struct soc_device_attribute soc_no_cpu_notifier[] = {
875
+ { .machine = "OMAP4430" },
876
+ { /* sentinel */ },
877
+};
887878
888879 /*** Device driver call backs ***/
889880
....@@ -1039,6 +1030,12 @@
10391030 }
10401031 }
10411032
1033
+#ifdef CONFIG_PM_SLEEP
1034
+ bgp->nb.notifier_call = bandgap_omap_cpu_notifier;
1035
+ if (!soc_device_match(soc_no_cpu_notifier))
1036
+ cpu_pm_register_notifier(&bgp->nb);
1037
+#endif
1038
+
10421039 return 0;
10431040
10441041 remove_last_cooling:
....@@ -1060,10 +1057,8 @@
10601057 put_fclock:
10611058 clk_put(bgp->fclock);
10621059 free_irqs:
1063
- if (TI_BANDGAP_HAS(bgp, TSHUT)) {
1064
- free_irq(gpio_to_irq(bgp->tshut_gpio), NULL);
1065
- gpio_free(bgp->tshut_gpio);
1066
- }
1060
+ if (TI_BANDGAP_HAS(bgp, TSHUT))
1061
+ free_irq(gpiod_to_irq(bgp->tshut_gpiod), NULL);
10671062
10681063 return ret;
10691064 }
....@@ -1074,7 +1069,10 @@
10741069 struct ti_bandgap *bgp = platform_get_drvdata(pdev);
10751070 int i;
10761071
1077
- /* First thing is to remove sensor interfaces */
1072
+ if (!soc_device_match(soc_no_cpu_notifier))
1073
+ cpu_pm_unregister_notifier(&bgp->nb);
1074
+
1075
+ /* Remove sensor interfaces */
10781076 for (i = 0; i < bgp->conf->sensor_count; i++) {
10791077 if (bgp->conf->sensors[i].unregister_cooling)
10801078 bgp->conf->sensors[i].unregister_cooling(bgp, i);
....@@ -1093,10 +1091,8 @@
10931091 if (TI_BANDGAP_HAS(bgp, TALERT))
10941092 free_irq(bgp->irq, bgp);
10951093
1096
- if (TI_BANDGAP_HAS(bgp, TSHUT)) {
1097
- free_irq(gpio_to_irq(bgp->tshut_gpio), NULL);
1098
- gpio_free(bgp->tshut_gpio);
1099
- }
1094
+ if (TI_BANDGAP_HAS(bgp, TSHUT))
1095
+ free_irq(gpiod_to_irq(bgp->tshut_gpiod), NULL);
11001096
11011097 return 0;
11021098 }
....@@ -1185,7 +1181,41 @@
11851181 if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
11861182 clk_disable_unprepare(bgp->fclock);
11871183
1184
+ bgp->is_suspended = true;
1185
+
11881186 return err;
1187
+}
1188
+
1189
+static int bandgap_omap_cpu_notifier(struct notifier_block *nb,
1190
+ unsigned long cmd, void *v)
1191
+{
1192
+ struct ti_bandgap *bgp;
1193
+
1194
+ bgp = container_of(nb, struct ti_bandgap, nb);
1195
+
1196
+ spin_lock(&bgp->lock);
1197
+ switch (cmd) {
1198
+ case CPU_CLUSTER_PM_ENTER:
1199
+ if (bgp->is_suspended)
1200
+ break;
1201
+ ti_bandgap_save_ctxt(bgp);
1202
+ ti_bandgap_power(bgp, false);
1203
+ if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
1204
+ clk_disable(bgp->fclock);
1205
+ break;
1206
+ case CPU_CLUSTER_PM_ENTER_FAILED:
1207
+ case CPU_CLUSTER_PM_EXIT:
1208
+ if (bgp->is_suspended)
1209
+ break;
1210
+ if (TI_BANDGAP_HAS(bgp, CLK_CTRL))
1211
+ clk_enable(bgp->fclock);
1212
+ ti_bandgap_power(bgp, true);
1213
+ ti_bandgap_restore_ctxt(bgp);
1214
+ break;
1215
+ }
1216
+ spin_unlock(&bgp->lock);
1217
+
1218
+ return NOTIFY_OK;
11891219 }
11901220
11911221 static int ti_bandgap_resume(struct device *dev)
....@@ -1196,6 +1226,7 @@
11961226 clk_prepare_enable(bgp->fclock);
11971227
11981228 ti_bandgap_power(bgp, true);
1229
+ bgp->is_suspended = false;
11991230
12001231 return ti_bandgap_restore_ctxt(bgp);
12011232 }