1 /*
2  * Copyright (c) 2019 Peter Bigot Consulting, LLC
3  * Copyright (c) 2016 Intel Corporation
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #ifndef ZEPHYR_DRIVERS_SENSOR_MCP9808_MCP9808_H_
9 #define ZEPHYR_DRIVERS_SENSOR_MCP9808_MCP9808_H_
10 
11 #include <errno.h>
12 
13 #include <zephyr/types.h>
14 #include <zephyr/device.h>
15 #include <zephyr/drivers/sensor.h>
16 #include <zephyr/sys/util.h>
17 #include <zephyr/drivers/i2c.h>
18 #include <zephyr/drivers/gpio.h>
19 
20 #define MCP9808_REG_CONFIG		0x01
21 #define MCP9808_REG_UPPER_LIMIT		0x02
22 #define MCP9808_REG_LOWER_LIMIT		0x03
23 #define MCP9808_REG_CRITICAL		0x04
24 #define MCP9808_REG_TEMP_AMB		0x05
25 
26 /* 16 bits control configuration and state.
27  *
28  * * Bit 0 controls alert signal output mode
29  * * Bit 1 controls interrupt polarity
30  * * Bit 2 disables upper and lower threshold checking
31  * * Bit 3 enables alert signal output
32  * * Bit 4 records alert status
33  * * Bit 5 records interrupt status
34  * * Bit 6 locks the upper/lower window registers
35  * * Bit 7 locks the critical register
36  * * Bit 8 enters shutdown mode
37  * * Bits 9-10 control threshold hysteresis
38  */
39 #define MCP9808_CFG_ALERT_MODE_INT	BIT(0)
40 #define MCP9808_CFG_ALERT_ENA		BIT(3)
41 #define MCP9808_CFG_ALERT_STATE		BIT(4)
42 #define MCP9808_CFG_INT_CLEAR		BIT(5)
43 
44 /* 16 bits are used for temperature and state encoding:
45  * * Bits 0..11 encode the temperature in a 2s complement signed value
46  *   in Celsius with 1/16 Cel resolution
47  * * Bit 12 is set to indicate a negative temperature
48  * * Bit 13 is set to indicate a temperature below the lower threshold
49  * * Bit 14 is set to indicate a temperature above the upper threshold
50  * * Bit 15 is set to indicate a temperature above the critical threshold
51  */
52 #define MCP9808_TEMP_SCALE_CEL		16 /* signed */
53 #define MCP9808_TEMP_SIGN_BIT		BIT(12)
54 #define MCP9808_TEMP_ABS_MASK		((uint16_t)(MCP9808_TEMP_SIGN_BIT - 1U))
55 #define MCP9808_TEMP_LWR_BIT		BIT(13)
56 #define MCP9808_TEMP_UPR_BIT		BIT(14)
57 #define MCP9808_TEMP_CRT_BIT		BIT(15)
58 
59 #define MCP9808_REG_RESOLUTION          0x08
60 
61 struct mcp9808_data {
62 	uint16_t reg_val;
63 
64 #ifdef CONFIG_MCP9808_TRIGGER
65 	struct gpio_callback alert_cb;
66 
67 	const struct device *dev;
68 
69 	const struct sensor_trigger *trig;
70 	sensor_trigger_handler_t trigger_handler;
71 #endif
72 
73 #ifdef CONFIG_MCP9808_TRIGGER_OWN_THREAD
74 	struct k_sem sem;
75 #endif
76 
77 #ifdef CONFIG_MCP9808_TRIGGER_GLOBAL_THREAD
78 	struct k_work work;
79 #endif
80 };
81 
82 struct mcp9808_config {
83 	struct i2c_dt_spec i2c;
84 	uint8_t resolution;
85 #ifdef CONFIG_MCP9808_TRIGGER
86 	struct gpio_dt_spec int_gpio;
87 #endif /* CONFIG_MCP9808_TRIGGER */
88 };
89 
90 int mcp9808_reg_read(const struct device *dev, uint8_t reg, uint16_t *val);
91 int mcp9808_reg_write_16bit(const struct device *dev, uint8_t reg,
92 			    uint16_t val);
93 int mcp9808_reg_write_8bit(const struct device *dev, uint8_t reg,
94 			   uint8_t val);
95 
96 #ifdef CONFIG_MCP9808_TRIGGER
97 int mcp9808_attr_set(const struct device *dev, enum sensor_channel chan,
98 		     enum sensor_attribute attr,
99 		     const struct sensor_value *val);
100 int mcp9808_trigger_set(const struct device *dev,
101 			const struct sensor_trigger *trig,
102 			sensor_trigger_handler_t handler);
103 int mcp9808_setup_interrupt(const struct device *dev);
104 #endif /* CONFIG_MCP9808_TRIGGER */
105 
106 /* Encode a signed temperature in scaled Celsius to the format used in
107  * register values.
108  */
mcp9808_temp_reg_from_signed(int temp)109 static inline uint16_t mcp9808_temp_reg_from_signed(int temp)
110 {
111 	/* Get the 12-bit 2s complement value */
112 	uint16_t rv = temp & MCP9808_TEMP_ABS_MASK;
113 
114 	if (temp < 0) {
115 		rv |= MCP9808_TEMP_SIGN_BIT;
116 	}
117 	return rv;
118 }
119 
120 /* Decode a register temperature value to a signed temperature in
121  * scaled Celsius.
122  */
mcp9808_temp_signed_from_reg(uint16_t reg)123 static inline int mcp9808_temp_signed_from_reg(uint16_t reg)
124 {
125 	int rv = reg & MCP9808_TEMP_ABS_MASK;
126 
127 	if (reg & MCP9808_TEMP_SIGN_BIT) {
128 		/* Convert 12-bit 2s complement to signed negative
129 		 * value.
130 		 */
131 		rv = -(1U + (rv ^ MCP9808_TEMP_ABS_MASK));
132 	}
133 	return rv;
134 }
135 
136 #endif /* ZEPHYR_DRIVERS_SENSOR_MCP9808_MCP9808_H_ */
137