Skip to content

Commit 959e6e0

Browse files
maass-hamburgChromeos LUCI
authored andcommitted
drivers: sensors: add jedec jc 42.4 compliant temperature sensor
This transforms the existing driver for the Microchip MCP9808 to be used as a generic driver to be used with all JEDEC JC 42.4 compliant temperature sensor chips. (cherry picked from commit 2293e66) Original-Signed-off-by: Fin Maaß <[email protected]> GitOrigin-RevId: 2293e66 Cr-Build-Id: 8738238973287044049 Cr-Build-Url: https://cr-buildbucket.appspot.com/build/8738238973287044049 Copybot-Job-Name: zephyr-main-copybot-downstream Change-Id: I3551f2aed64a62624fd396a63e3337652f39170a Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/zephyr/+/5827580 Commit-Queue: Ting Shen <[email protected]> Tested-by: Ting Shen <[email protected]> Reviewed-by: Ting Shen <[email protected]> Tested-by: ChromeOS Prod (Robot) <[email protected]>
1 parent f2e4076 commit 959e6e0

30 files changed

+428
-411
lines changed

drivers/sensor/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ add_subdirectory(espressif)
1010
add_subdirectory(honeywell)
1111
add_subdirectory(infineon)
1212
add_subdirectory(ite)
13+
add_subdirectory(jedec)
1314
add_subdirectory(maxim)
1415
add_subdirectory(meas)
1516
add_subdirectory(microchip)

drivers/sensor/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ source "drivers/sensor/espressif/Kconfig"
9494
source "drivers/sensor/honeywell/Kconfig"
9595
source "drivers/sensor/infineon/Kconfig"
9696
source "drivers/sensor/ite/Kconfig"
97+
source "drivers/sensor/jedec/Kconfig"
9798
source "drivers/sensor/maxim/Kconfig"
9899
source "drivers/sensor/meas/Kconfig"
99100
source "drivers/sensor/microchip/Kconfig"
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Copyright (c) 2024 Vogl Electronic GmbH
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
# zephyr-keep-sorted-start
5+
add_subdirectory_ifdef(CONFIG_JC42 jc42)
6+
# zephyr-keep-sorted-stop

drivers/sensor/jedec/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Copyright (c) 2024 Vogl Electronic GmbH
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
# zephyr-keep-sorted-start
5+
source "drivers/sensor/jedec/jc42/Kconfig"
6+
# zephyr-keep-sorted-stop
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Copyright (c) 2024 Vogl Electronic GmbH
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
zephyr_library()
5+
6+
zephyr_library_sources(jc42.c)
7+
zephyr_library_sources_ifdef(CONFIG_JC42_TRIGGER jc42_trigger.c)

drivers/sensor/jedec/jc42/Kconfig

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# JEDEC JC 42.4 compliant temperature sensor configuration options
2+
3+
# Copyright (c) 2016 Intel Corporation
4+
# Copyright (c) 2024 Vogl Electronic GmbH
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
menuconfig JC42
8+
bool "JC42 temperature sensor"
9+
default y
10+
depends on DT_HAS_JEDEC_JC_42_4_TEMP_ENABLED
11+
select I2C
12+
help
13+
Enable driver for JC42 temperature sensor.
14+
15+
if JC42
16+
17+
choice
18+
prompt "JC42 trigger mode"
19+
default JC42_TRIGGER_NONE
20+
21+
config JC42_TRIGGER_NONE
22+
bool "No trigger"
23+
24+
config JC42_TRIGGER_GLOBAL_THREAD
25+
depends on GPIO
26+
select JC42_TRIGGER
27+
bool "Use global thread"
28+
29+
config JC42_TRIGGER_OWN_THREAD
30+
depends on GPIO
31+
select JC42_TRIGGER
32+
bool "Use own thread"
33+
34+
endchoice
35+
36+
config JC42_TRIGGER
37+
bool
38+
39+
config JC42_THREAD_STACK_SIZE
40+
int "Sensor delayed work thread stack size"
41+
depends on JC42_TRIGGER_OWN_THREAD
42+
default 1024
43+
44+
config JC42_THREAD_PRIORITY
45+
int "JC42 thread priority"
46+
depends on JC42_TRIGGER_OWN_THREAD
47+
default 10
48+
49+
endif # JC42

drivers/sensor/jedec/jc42/jc42.c

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* Copyright (c) 2019 Peter Bigot Consulting, LLC
3+
* Copyright (c) 2016 Intel Corporation
4+
* Copyright (c) 2024 Vogl Electronic GmbH
5+
*
6+
* SPDX-License-Identifier: Apache-2.0
7+
*/
8+
9+
#define DT_DRV_COMPAT jedec_jc_42_4_temp
10+
11+
#include <errno.h>
12+
13+
#include <zephyr/kernel.h>
14+
#include <zephyr/drivers/i2c.h>
15+
#include <zephyr/init.h>
16+
#include <zephyr/sys/byteorder.h>
17+
#include <zephyr/sys/__assert.h>
18+
#include <zephyr/logging/log.h>
19+
20+
#include "jc42.h"
21+
22+
LOG_MODULE_REGISTER(JC42, CONFIG_SENSOR_LOG_LEVEL);
23+
24+
int jc42_reg_read(const struct device *dev, uint8_t reg, uint16_t *val)
25+
{
26+
const struct jc42_config *cfg = dev->config;
27+
int rc = i2c_write_read_dt(&cfg->i2c, &reg, sizeof(reg), val, sizeof(*val));
28+
29+
if (rc == 0) {
30+
*val = sys_be16_to_cpu(*val);
31+
}
32+
33+
return rc;
34+
}
35+
36+
int jc42_reg_write_16bit(const struct device *dev, uint8_t reg, uint16_t val)
37+
{
38+
const struct jc42_config *cfg = dev->config;
39+
40+
uint8_t buf[3];
41+
42+
buf[0] = reg;
43+
sys_put_be16(val, &buf[1]);
44+
45+
return i2c_write_dt(&cfg->i2c, buf, sizeof(buf));
46+
}
47+
48+
int jc42_reg_write_8bit(const struct device *dev, uint8_t reg, uint8_t val)
49+
{
50+
const struct jc42_config *cfg = dev->config;
51+
uint8_t buf[2] = {
52+
reg,
53+
val,
54+
};
55+
56+
return i2c_write_dt(&cfg->i2c, buf, sizeof(buf));
57+
}
58+
59+
static int jc42_set_temperature_resolution(const struct device *dev, uint8_t resolution)
60+
{
61+
return jc42_reg_write_8bit(dev, JC42_REG_RESOLUTION, resolution);
62+
}
63+
64+
static int jc42_sample_fetch(const struct device *dev, enum sensor_channel chan)
65+
{
66+
struct jc42_data *data = dev->data;
67+
68+
__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_AMBIENT_TEMP);
69+
70+
return jc42_reg_read(dev, JC42_REG_TEMP_AMB, &data->reg_val);
71+
}
72+
73+
static int jc42_channel_get(const struct device *dev, enum sensor_channel chan,
74+
struct sensor_value *val)
75+
{
76+
const struct jc42_data *data = dev->data;
77+
int temp = jc42_temp_signed_from_reg(data->reg_val);
78+
79+
__ASSERT_NO_MSG(chan == SENSOR_CHAN_AMBIENT_TEMP);
80+
81+
if (chan != SENSOR_CHAN_AMBIENT_TEMP) {
82+
return -ENOTSUP;
83+
}
84+
85+
val->val1 = temp / JC42_TEMP_SCALE_CEL;
86+
temp -= val->val1 * JC42_TEMP_SCALE_CEL;
87+
val->val2 = (temp * 1000000) / JC42_TEMP_SCALE_CEL;
88+
89+
return 0;
90+
}
91+
92+
static const struct sensor_driver_api jc42_api_funcs = {
93+
.sample_fetch = jc42_sample_fetch,
94+
.channel_get = jc42_channel_get,
95+
#ifdef CONFIG_JC42_TRIGGER
96+
.attr_set = jc42_attr_set,
97+
.trigger_set = jc42_trigger_set,
98+
#endif /* CONFIG_JC42_TRIGGER */
99+
};
100+
101+
int jc42_init(const struct device *dev)
102+
{
103+
const struct jc42_config *cfg = dev->config;
104+
int rc = 0;
105+
106+
if (!device_is_ready(cfg->i2c.bus)) {
107+
LOG_ERR("Bus device is not ready");
108+
return -ENODEV;
109+
}
110+
111+
rc = jc42_set_temperature_resolution(dev, cfg->resolution);
112+
if (rc) {
113+
LOG_ERR("Could not set the resolution of jc42 module");
114+
return rc;
115+
}
116+
117+
#ifdef CONFIG_JC42_TRIGGER
118+
if (cfg->int_gpio.port) {
119+
rc = jc42_setup_interrupt(dev);
120+
}
121+
#endif /* CONFIG_JC42_TRIGGER */
122+
123+
return rc;
124+
}
125+
126+
#define JC42_DEFINE(inst) \
127+
static struct jc42_data jc42_data_##inst; \
128+
\
129+
static const struct jc42_config jc42_config_##inst = { \
130+
.i2c = I2C_DT_SPEC_INST_GET(inst), \
131+
.resolution = DT_INST_PROP(inst, resolution), \
132+
IF_ENABLED(CONFIG_JC42_TRIGGER, \
133+
(.int_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, {0}),))}; \
134+
\
135+
SENSOR_DEVICE_DT_INST_DEFINE(inst, jc42_init, NULL, &jc42_data_##inst, \
136+
&jc42_config_##inst, POST_KERNEL, \
137+
CONFIG_SENSOR_INIT_PRIORITY, &jc42_api_funcs);
138+
139+
DT_INST_FOREACH_STATUS_OKAY(JC42_DEFINE)

drivers/sensor/jedec/jc42/jc42.h

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
* Copyright (c) 2019 Peter Bigot Consulting, LLC
3+
* Copyright (c) 2016 Intel Corporation
4+
* Copyright (c) 2024 Vogl Electronic GmbH
5+
*
6+
* SPDX-License-Identifier: Apache-2.0
7+
*/
8+
9+
#ifndef ZEPHYR_DRIVERS_SENSOR_JEDEC_JC42_H_
10+
#define ZEPHYR_DRIVERS_SENSOR_JEDEC_JC42_H_
11+
12+
#include <errno.h>
13+
14+
#include <zephyr/types.h>
15+
#include <zephyr/device.h>
16+
#include <zephyr/drivers/sensor.h>
17+
#include <zephyr/sys/util.h>
18+
#include <zephyr/drivers/i2c.h>
19+
#include <zephyr/drivers/gpio.h>
20+
21+
#define JC42_REG_CONFIG 0x01
22+
#define JC42_REG_UPPER_LIMIT 0x02
23+
#define JC42_REG_LOWER_LIMIT 0x03
24+
#define JC42_REG_CRITICAL 0x04
25+
#define JC42_REG_TEMP_AMB 0x05
26+
27+
/* 16 bits control configuration and state.
28+
*
29+
* * Bit 0 controls alert signal output mode
30+
* * Bit 1 controls interrupt polarity
31+
* * Bit 2 disables upper and lower threshold checking
32+
* * Bit 3 enables alert signal output
33+
* * Bit 4 records alert status
34+
* * Bit 5 records interrupt status
35+
* * Bit 6 locks the upper/lower window registers
36+
* * Bit 7 locks the critical register
37+
* * Bit 8 enters shutdown mode
38+
* * Bits 9-10 control threshold hysteresis
39+
*/
40+
#define JC42_CFG_ALERT_MODE_INT BIT(0)
41+
#define JC42_CFG_ALERT_ENA BIT(3)
42+
#define JC42_CFG_ALERT_STATE BIT(4)
43+
#define JC42_CFG_INT_CLEAR BIT(5)
44+
45+
/* 16 bits are used for temperature and state encoding:
46+
* * Bits 0..11 encode the temperature in a 2s complement signed value
47+
* in Celsius with 1/16 Cel resolution
48+
* * Bit 12 is set to indicate a negative temperature
49+
* * Bit 13 is set to indicate a temperature below the lower threshold
50+
* * Bit 14 is set to indicate a temperature above the upper threshold
51+
* * Bit 15 is set to indicate a temperature above the critical threshold
52+
*/
53+
#define JC42_TEMP_SCALE_CEL 16 /* signed */
54+
#define JC42_TEMP_SIGN_BIT BIT(12)
55+
#define JC42_TEMP_ABS_MASK ((uint16_t)(JC42_TEMP_SIGN_BIT - 1U))
56+
#define JC42_TEMP_LWR_BIT BIT(13)
57+
#define JC42_TEMP_UPR_BIT BIT(14)
58+
#define JC42_TEMP_CRT_BIT BIT(15)
59+
60+
#define JC42_REG_RESOLUTION 0x08
61+
62+
struct jc42_data {
63+
uint16_t reg_val;
64+
65+
#ifdef CONFIG_JC42_TRIGGER
66+
struct gpio_callback alert_cb;
67+
68+
const struct device *dev;
69+
70+
const struct sensor_trigger *trig;
71+
sensor_trigger_handler_t trigger_handler;
72+
#endif
73+
74+
#ifdef CONFIG_JC42_TRIGGER_OWN_THREAD
75+
struct k_sem sem;
76+
#endif
77+
78+
#ifdef CONFIG_JC42_TRIGGER_GLOBAL_THREAD
79+
struct k_work work;
80+
#endif
81+
};
82+
83+
struct jc42_config {
84+
struct i2c_dt_spec i2c;
85+
uint8_t resolution;
86+
#ifdef CONFIG_JC42_TRIGGER
87+
struct gpio_dt_spec int_gpio;
88+
#endif /* CONFIG_JC42_TRIGGER */
89+
};
90+
91+
int jc42_reg_read(const struct device *dev, uint8_t reg, uint16_t *val);
92+
int jc42_reg_write_16bit(const struct device *dev, uint8_t reg, uint16_t val);
93+
int jc42_reg_write_8bit(const struct device *dev, uint8_t reg, uint8_t val);
94+
95+
#ifdef CONFIG_JC42_TRIGGER
96+
int jc42_attr_set(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr,
97+
const struct sensor_value *val);
98+
int jc42_trigger_set(const struct device *dev, const struct sensor_trigger *trig,
99+
sensor_trigger_handler_t handler);
100+
int jc42_setup_interrupt(const struct device *dev);
101+
#endif /* CONFIG_JC42_TRIGGER */
102+
103+
/* Encode a signed temperature in scaled Celsius to the format used in
104+
* register values.
105+
*/
106+
static inline uint16_t jc42_temp_reg_from_signed(int temp)
107+
{
108+
/* Get the 12-bit 2s complement value */
109+
uint16_t rv = temp & JC42_TEMP_ABS_MASK;
110+
111+
if (temp < 0) {
112+
rv |= JC42_TEMP_SIGN_BIT;
113+
}
114+
return rv;
115+
}
116+
117+
/* Decode a register temperature value to a signed temperature in
118+
* scaled Celsius.
119+
*/
120+
static inline int jc42_temp_signed_from_reg(uint16_t reg)
121+
{
122+
int rv = reg & JC42_TEMP_ABS_MASK;
123+
124+
if (reg & JC42_TEMP_SIGN_BIT) {
125+
/* Convert 12-bit 2s complement to signed negative
126+
* value.
127+
*/
128+
rv = -(1U + (rv ^ JC42_TEMP_ABS_MASK));
129+
}
130+
return rv;
131+
}
132+
133+
#endif /* ZEPHYR_DRIVERS_SENSOR_JEDEC_JC42_H_ */

0 commit comments

Comments
 (0)