Skip to content

Commit cd8d956

Browse files
committed
drivers: sensor: Enable NXP pmc tmpsns driver
This commit introduced NXP pmc temperature sensor (pmc-tmpsns) driver. Signed-off-by: Zhaoxiang Jin <[email protected]>
1 parent 73fb2d6 commit cd8d956

File tree

6 files changed

+183
-0
lines changed

6 files changed

+183
-0
lines changed

drivers/sensor/nxp/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ add_subdirectory_ifdef(CONFIG_FXLS8974 fxls8974)
77
add_subdirectory_ifdef(CONFIG_FXOS8700 fxos8700)
88
add_subdirectory_ifdef(CONFIG_LPADC_TEMP40 nxp_lpadc_temp40)
99
add_subdirectory_ifdef(CONFIG_MCUX_LPCMP mcux_lpcmp)
10+
add_subdirectory_ifdef(CONFIG_NXP_PMC_TMPSNS nxp_pmc_tmpsns)
1011
add_subdirectory_ifdef(CONFIG_NXP_TEMPMON nxp_tempmon)
1112
add_subdirectory_ifdef(CONFIG_NXP_TMPSNS nxp_tmpsns)
1213
add_subdirectory_ifdef(CONFIG_P3T1755 p3t1755)

drivers/sensor/nxp/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ source "drivers/sensor/nxp/mcux_acmp/Kconfig"
99
source "drivers/sensor/nxp/mcux_lpcmp/Kconfig"
1010
source "drivers/sensor/nxp/nxp_kinetis_temp/Kconfig"
1111
source "drivers/sensor/nxp/nxp_lpadc_temp40/Kconfig"
12+
source "drivers/sensor/nxp/nxp_pmc_tmpsns/Kconfig"
1213
source "drivers/sensor/nxp/nxp_tempmon/Kconfig"
1314
source "drivers/sensor/nxp/nxp_tmpsns/Kconfig"
1415
source "drivers/sensor/nxp/p3t1755/Kconfig"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Copyright 2025 NXP
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
zephyr_library()
5+
zephyr_library_sources(nxp_pmc_tmpsns.c)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Copyright 2025 NXP
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config NXP_PMC_TMPSNS
5+
bool "NXP PMC Temperature Sensor (TMPSNS)"
6+
default y
7+
depends on DT_HAS_NXP_PMC_TMPSNS_ENABLED
8+
select FPU if CPU_HAS_FPU
9+
help
10+
Enable driver for the NXP PMC temperature sensor.
11+
This is used to retrieve on-die operational temperature.
12+
13+
if NXP_PMC_TMPSNS
14+
config NXP_PMC_TMPSNS_CALIBRATION_OTP_FUSE_INDEX
15+
int "OTP FUSE index"
16+
default 77 if SOC_SERIES_IMXRT7XX
17+
help
18+
TSENS_CAL is an 8-bit signed calibration constant
19+
retrieved from non-volatile memory. We need this
20+
index to read the fuse to get TSENS_CAL.
21+
endif
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* Copyright 2025 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "fsl_romapi_otp.h"
8+
#include <zephyr/device.h>
9+
#include <zephyr/devicetree.h>
10+
#include <zephyr/drivers/sensor.h>
11+
#include <zephyr/drivers/adc.h>
12+
#include <zephyr/logging/log.h>
13+
14+
LOG_MODULE_REGISTER(nxp_pmc_tmpsns, CONFIG_SENSOR_LOG_LEVEL);
15+
16+
#define DT_DRV_COMPAT nxp_pmc_tmpsns
17+
18+
struct nxp_pmc_tmpsns_config {
19+
const struct device *adc;
20+
struct adc_sequence adc_seq;
21+
struct adc_channel_cfg ch_cfg;
22+
};
23+
24+
struct nxp_pmc_tmpsns_data {
25+
uint16_t buffer;
26+
uint32_t pmc_tmpsns_calibration;
27+
float pmc_tmpsns_value;
28+
};
29+
30+
static int nxp_pmc_tmpsns_sample_fetch(const struct device *dev, enum sensor_channel chan)
31+
{
32+
uint8_t pmc_tmpsns_select[15] = {0, 1, 3, 2, 6, 7, 5, 4, 5, 7, 6, 2, 3, 1, 0};
33+
const struct nxp_pmc_tmpsns_config *config = dev->config;
34+
struct nxp_pmc_tmpsns_data *data = dev->data;
35+
uint16_t pmc_tmpsns_value[15] = {0};
36+
float cm_vref, cm_ctat, cm_temp;
37+
int8_t calibration = 0;
38+
int ret;
39+
40+
if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) {
41+
return -ENOTSUP;
42+
}
43+
44+
for (uint8_t index = 0; index < 15; ++index) {
45+
PMC0->TSENSOR = PMC_TSENSOR_TSENSM(pmc_tmpsns_select[index]);
46+
47+
ret = adc_read(config->adc, &config->adc_seq);
48+
if (ret) {
49+
LOG_ERR("Failed to read ADC channels with code %d", ret);
50+
return ret;
51+
}
52+
pmc_tmpsns_value[index] = data->buffer;
53+
}
54+
55+
cm_ctat = (float)(2 * pmc_tmpsns_value[1] - pmc_tmpsns_value[2] +
56+
2 * pmc_tmpsns_value[13] - pmc_tmpsns_value[12] +
57+
2 * pmc_tmpsns_value[6] - pmc_tmpsns_value[5] +
58+
2 * pmc_tmpsns_value[8] - pmc_tmpsns_value[9]) / 4.0f;
59+
60+
cm_temp = (float)(2 * pmc_tmpsns_value[0] - pmc_tmpsns_value[3] +
61+
2 * pmc_tmpsns_value[14] - pmc_tmpsns_value[11] +
62+
4 * pmc_tmpsns_value[7] - pmc_tmpsns_value[4] -
63+
pmc_tmpsns_value[10]) / 4.0f;
64+
65+
calibration = (int8_t)(data->pmc_tmpsns_calibration & 0xFF);
66+
67+
cm_vref = cm_ctat + (953.36f + calibration) * cm_temp / 2048;
68+
69+
data->pmc_tmpsns_value = 370.98f * (cm_temp / cm_vref) - 273.15f;
70+
71+
return 0;
72+
}
73+
74+
static int nxp_pmc_tmpsns_channel_get(const struct device *dev,
75+
enum sensor_channel chan,
76+
struct sensor_value *val)
77+
{
78+
const struct nxp_pmc_tmpsns_data *data = dev->data;
79+
80+
if (chan != SENSOR_CHAN_DIE_TEMP) {
81+
return -ENOTSUP;
82+
}
83+
84+
return sensor_value_from_double(val, data->pmc_tmpsns_value);
85+
}
86+
87+
static int nxp_pmc_tmpsns_init(const struct device *dev)
88+
{
89+
const struct nxp_pmc_tmpsns_config *config = dev->config;
90+
struct nxp_pmc_tmpsns_data *data = dev->data;
91+
int ret;
92+
93+
if (!device_is_ready(config->adc)) {
94+
LOG_ERR("ADC device not ready");
95+
return -ENODEV;
96+
}
97+
98+
ret = adc_channel_setup(config->adc, &config->ch_cfg);
99+
if (ret) {
100+
LOG_ERR("Failed to setup ADC channel with code %d", ret);
101+
return ret;
102+
}
103+
104+
ret = otp_fuse_read(CONFIG_NXP_PMC_TMPSNS_CALIBRATION_OTP_FUSE_INDEX,
105+
&(data->pmc_tmpsns_calibration));
106+
if (ret) {
107+
LOG_ERR("Failed to get calibration value form FUSE.");
108+
return -ENOTSUP;
109+
}
110+
111+
return 0;
112+
}
113+
114+
static DEVICE_API(sensor, nxp_pmc_tmpsns_api) = {
115+
.sample_fetch = nxp_pmc_tmpsns_sample_fetch,
116+
.channel_get = nxp_pmc_tmpsns_channel_get,
117+
};
118+
119+
#define NXP_PMC_TMPSNS_INIT(inst) \
120+
static struct nxp_pmc_tmpsns_data _CONCAT(data, inst); \
121+
\
122+
static const struct nxp_pmc_tmpsns_config _CONCAT(config, inst) = { \
123+
.adc = DEVICE_DT_GET(DT_INST_IO_CHANNELS_CTLR(inst)), \
124+
.adc_seq = { \
125+
.channels = BIT(DT_INST_IO_CHANNELS_INPUT(inst)), \
126+
.buffer = &_CONCAT(data, inst).buffer, \
127+
.buffer_size = sizeof(_CONCAT(data, inst)), \
128+
.resolution = 16, \
129+
.oversampling = 7, \
130+
}, \
131+
.ch_cfg = ADC_CHANNEL_CFG_DT(DT_CHILD(DT_INST_IO_CHANNELS_CTLR(inst), \
132+
UTIL_CAT(channel_, DT_INST_IO_CHANNELS_INPUT(inst)))), \
133+
}; \
134+
\
135+
SENSOR_DEVICE_DT_INST_DEFINE(inst, nxp_pmc_tmpsns_init, NULL, \
136+
&_CONCAT(data, inst), &_CONCAT(config, inst), \
137+
POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \
138+
&nxp_pmc_tmpsns_api);
139+
140+
DT_INST_FOREACH_STATUS_OKAY(NXP_PMC_TMPSNS_INIT)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright NXP 2025
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: NXP PMC temperature sensor (PMC-TMPSNS)
5+
6+
compatible: "nxp,pmc-tmpsns"
7+
8+
include: sensor-device.yaml
9+
10+
properties:
11+
io-channels:
12+
required: true
13+
description: |
14+
This should point to an ADC channel (e.g., <&adc0 0>)
15+
to read from the PMC internal temperature sensor.

0 commit comments

Comments
 (0)