1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
7 #include <linux/module.h>
9 #include <linux/platform_device.h>
11 #include <linux/slab.h>
12 #include <linux/thermal.h>
15 static int tsens_get_temp(void *data
, int *temp
)
17 const struct tsens_sensor
*s
= data
;
18 struct tsens_device
*tmdev
= s
->tmdev
;
20 return tmdev
->ops
->get_temp(tmdev
, s
->id
, temp
);
23 static int tsens_get_trend(void *p
, int trip
, enum thermal_trend
*trend
)
25 const struct tsens_sensor
*s
= p
;
26 struct tsens_device
*tmdev
= s
->tmdev
;
28 if (tmdev
->ops
->get_trend
)
29 return tmdev
->ops
->get_trend(tmdev
, s
->id
, trend
);
34 static int __maybe_unused
tsens_suspend(struct device
*dev
)
36 struct tsens_device
*tmdev
= dev_get_drvdata(dev
);
38 if (tmdev
->ops
&& tmdev
->ops
->suspend
)
39 return tmdev
->ops
->suspend(tmdev
);
44 static int __maybe_unused
tsens_resume(struct device
*dev
)
46 struct tsens_device
*tmdev
= dev_get_drvdata(dev
);
48 if (tmdev
->ops
&& tmdev
->ops
->resume
)
49 return tmdev
->ops
->resume(tmdev
);
54 static SIMPLE_DEV_PM_OPS(tsens_pm_ops
, tsens_suspend
, tsens_resume
);
56 static const struct of_device_id tsens_table
[] = {
58 .compatible
= "qcom,msm8916-tsens",
61 .compatible
= "qcom,msm8974-tsens",
64 .compatible
= "qcom,msm8996-tsens",
67 .compatible
= "qcom,tsens-v2",
68 .data
= &data_tsens_v2
,
72 MODULE_DEVICE_TABLE(of
, tsens_table
);
74 static const struct thermal_zone_of_device_ops tsens_of_ops
= {
75 .get_temp
= tsens_get_temp
,
76 .get_trend
= tsens_get_trend
,
79 static int tsens_register(struct tsens_device
*tmdev
)
82 struct thermal_zone_device
*tzd
;
84 for (i
= 0; i
< tmdev
->num_sensors
; i
++) {
85 tmdev
->sensor
[i
].tmdev
= tmdev
;
86 tmdev
->sensor
[i
].id
= i
;
87 tzd
= devm_thermal_zone_of_sensor_register(tmdev
->dev
, i
,
92 tmdev
->sensor
[i
].tzd
= tzd
;
93 if (tmdev
->ops
->enable
)
94 tmdev
->ops
->enable(tmdev
, i
);
99 static int tsens_probe(struct platform_device
*pdev
)
103 struct device_node
*np
;
104 struct tsens_device
*tmdev
;
105 const struct tsens_data
*data
;
106 const struct of_device_id
*id
;
109 if (pdev
->dev
.of_node
)
112 dev
= pdev
->dev
.parent
;
116 id
= of_match_node(tsens_table
, np
);
122 num_sensors
= data
->num_sensors
;
125 of_property_read_u32(np
, "#qcom,sensors", &num_sensors
);
127 if (num_sensors
<= 0) {
128 dev_err(dev
, "invalid number of sensors\n");
132 tmdev
= devm_kzalloc(dev
,
133 struct_size(tmdev
, sensor
, num_sensors
),
139 tmdev
->num_sensors
= num_sensors
;
140 tmdev
->ops
= data
->ops
;
141 for (i
= 0; i
< tmdev
->num_sensors
; i
++) {
143 tmdev
->sensor
[i
].hw_id
= data
->hw_ids
[i
];
145 tmdev
->sensor
[i
].hw_id
= i
;
147 for (i
= 0; i
< REG_ARRAY_SIZE
; i
++) {
148 tmdev
->reg_offsets
[i
] = data
->reg_offsets
[i
];
151 if (!tmdev
->ops
|| !tmdev
->ops
->init
|| !tmdev
->ops
->get_temp
)
154 ret
= tmdev
->ops
->init(tmdev
);
156 dev_err(dev
, "tsens init failed\n");
160 if (tmdev
->ops
->calibrate
) {
161 ret
= tmdev
->ops
->calibrate(tmdev
);
163 dev_err(dev
, "tsens calibration failed\n");
168 ret
= tsens_register(tmdev
);
170 platform_set_drvdata(pdev
, tmdev
);
175 static int tsens_remove(struct platform_device
*pdev
)
177 struct tsens_device
*tmdev
= platform_get_drvdata(pdev
);
179 if (tmdev
->ops
->disable
)
180 tmdev
->ops
->disable(tmdev
);
185 static struct platform_driver tsens_driver
= {
186 .probe
= tsens_probe
,
187 .remove
= tsens_remove
,
189 .name
= "qcom-tsens",
191 .of_match_table
= tsens_table
,
194 module_platform_driver(tsens_driver
);
196 MODULE_LICENSE("GPL v2");
197 MODULE_DESCRIPTION("QCOM Temperature Sensor driver");
198 MODULE_ALIAS("platform:qcom-tsens");