1 /*
2  * Copyright (c) 2021 Jimmy Johnson <catch22@fastmail.net>
3  * Copyright (c) 2022 T-Mobile USA, Inc.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #ifndef ZEPHYR_DRIVERS_SENSOR_TMP108_TMP108_H_
9 #define ZEPHYR_DRIVERS_SENSOR_TMP108_TMP108_H_
10 
11 #include <stdint.h>
12 
13 #include <zephyr/drivers/i2c.h>
14 #include <zephyr/drivers/sensor.h>
15 #include <zephyr/drivers/gpio.h>
16 #include <zephyr/drivers/sensor/tmp108.h>
17 
18 #define TI_TMP108_REG_TEMP		0x00   /** Temperature register */
19 #define TI_TMP108_REG_CONF		0x01   /** Configuration register */
20 #define TI_TMP108_REG_LOW_LIMIT		0x02   /** Low alert set register */
21 #define TI_TMP108_REG_HIGH_LIMIT	0x03   /** High alert set register */
22 
23 #define AMS_AS6212_CONF                                                                            \
24 	{.CONF_CR0 = 0x0040,                                                                       \
25 	 .CONF_CR1 = 0x0080,                                                                       \
26 	 .CONF_SLEEP = 0x0100,                                                                     \
27 	 .CONF_M1 = 0x0000,                                                                        \
28 	 .CONF_TM = 0x0200,                                                                        \
29 	 .CONF_M0 = 0x8000,                                                                        \
30 	 .CONF_RST = 0x0080,                                                                       \
31 	 .TEMP_MULT = 15625,                                                                       \
32 	 .TEMP_DIV = 2,                                                                            \
33 	 IF_ENABLED(CONFIG_TMP108_ALERT_INTERRUPTS, (.CONF_POL = 0x0400))}
34 
35 #define TI_TMP108_CONF                                                                             \
36 	{.CONF_M0 = 0x0100,                                                                        \
37 	 .CONF_M1 = 0x0200,                                                                        \
38 	 .CONF_TM = 0x0400,                                                                        \
39 	 .CONF_CR0 = 0x2000,                                                                       \
40 	 .CONF_CR1 = 0x4000,                                                                       \
41 	 .CONF_RST = 0x0022,                                                                       \
42 	 .TEMP_MULT = 15625,                                                                       \
43 	 .TEMP_DIV = 4,                                                                            \
44 	 IF_ENABLED(CONFIG_TMP108_ALERT_INTERRUPTS,                                                \
45 		    (.CONF_HYS0 = 0x0010, .CONF_HYS1 = 0x0020, .CONF_POL = 0x0080))}
46 
47 #define TI_TMP108_MODE_SHUTDOWN(x) 0
48 #define TI_TMP108_MODE_ONE_SHOT(x) (TI_TMP108_CONF_M0(x) | TI_TMP108_CONF_SLEEP(x))
49 #define TI_TMP108_MODE_CONTINUOUS(x) TI_TMP108_CONF_M1(x)
50 #define TI_TMP108_MODE_MASK(x)	~(TI_TMP108_CONF_M0(x) | \
51 				  TI_TMP108_CONF_M1(x) | \
52 				  TI_TMP108_CONF_SLEEP(x))
53 
54 #define TI_TMP108_FREQ_4_SECS(x) 0
55 #define TI_TMP108_FREQ_1_HZ(x) TI_TMP108_GET_CONF(x, CONF_CR0)
56 #define TI_TMP108_FREQ_4_HZ(x) TI_TMP108_GET_CONF(x, CONF_CR1)
57 #define TI_TMP108_FREQ_16_HZ(x)	(TI_TMP108_GET_CONF(x, CONF_CR1) | \
58 				TI_TMP108_GET_CONF(x, CONF_CR0))
59 #define AMS_AS6212_FREQ_8_HZ(x) (TI_TMP108_GET_CONF(x, CONF_CR1) | TI_TMP108_GET_CONF(x, CONF_CR0))
60 #define TI_TMP108_FREQ_MASK(x)	~(TI_TMP108_GET_CONF(x, CONF_CR1) | \
61 				TI_TMP108_GET_CONF(x, CONF_CR0))
62 
63 #define TI_TMP108_CONF_POL_LOW(x) 0
64 #define TI_TMP108_CONF_POL_HIGH(x) TI_TMP108_GET_CONF(x, CONF_POL)
65 #define TI_TMP108_CONF_POL_MASK(x) ~(TI_TMP108_GET_CONF(x, CONF_POL))
66 
67 #define TI_TMP108_CONF_TM_CMP(x) 0
68 #define TI_TMP108_CONF_TM_INT(x) TI_TMP108_GET_CONF(x, CONF_TM)
69 #define TI_TMP108_CONF_TM_MASK(x) ~(TI_TMP108_GET_CONF(x, CONF_TM))
70 
71 #define TI_TMP108_HYSTER_0_C(x)	0
72 #define TI_TMP108_HYSTER_1_C(x)	TI_TMP108_GET_CONF(x, CONF_HYS0)
73 #define TI_TMP108_HYSTER_2_C(x)	TI_TMP108_GET_CONF(x, CONF_HYS1)
74 #define TI_TMP108_HYSTER_4_C(x)	(TI_TMP108_GET_CONF(x, CONF_HYS1) | \
75 				TI_TMP108_GET_CONF(x, CONF_HYS0))
76 #define TI_TMP108_HYSTER_MASK(x) ~(TI_TMP108_GET_CONF(x, CONF_HYS1) | \
77 				 TI_TMP108_GET_CONF(x, CONF_HYS0))
78 
79 #define TI_TMP108_CONF_M1(x) TI_TMP108_GET_CONF(x, CONF_M1)
80 #define TI_TMP108_CONF_M0(x) TI_TMP108_GET_CONF(x, CONF_M0)
81 #define TI_TMP108_CONF_SLEEP(x) TI_TMP108_GET_CONF(x, CONF_SLEEP)
82 
83 #define TMP108_TEMP_MULTIPLIER(x)	TI_TMP108_GET_CONF(x, TEMP_MULT)
84 #define TMP108_TEMP_DIVISOR(x)	TI_TMP108_GET_CONF(x, TEMP_DIV)
85 #define TMP108_CONF_RST(x)	TI_TMP108_GET_CONF(x, CONF_RST)
86 
87 #define TI_TMP108_CONF_NA 0x0000
88 
89 struct tmp_108_reg_def {
90 	uint16_t CONF_M0;    /** Mode 1 configuration bit */
91 	uint16_t CONF_M1;    /** Mode 2 configuration bit */
92 	uint16_t CONF_SLEEP; /** Sleep mode configuration bit */
93 	uint16_t CONF_CR0;   /** Conversion rate 1 configuration bit */
94 	uint16_t CONF_CR1;   /** Conversion rate 2 configuration bit */
95 	uint16_t CONF_TM;    /** Thermostat mode setting bit */
96 	int32_t TEMP_MULT;   /** Temperature multiplier */
97 	int32_t TEMP_DIV;    /** Temperature divisor */
98 	uint16_t CONF_RST;   /** default reset values on init */
99 #ifdef CONFIG_TMP108_ALERT_INTERRUPTS
100 	uint16_t CONF_POL;  /** Alert pin Polarity configuration bit */
101 	uint16_t CONF_HYS1; /** Temperature hysteresis config 1 bit  */
102 	uint16_t CONF_HYS0; /** Temperature hysteresis config 2 bit */
103 #endif
104 };
105 
106 #define TI_TMP108_GET_CONF(x, cfg) ((struct tmp108_config *)(x->config))->reg_def.cfg
107 
108 struct tmp108_config {
109 	const struct i2c_dt_spec i2c_spec;
110 	struct tmp_108_reg_def reg_def;
111 #ifdef CONFIG_TMP108_ALERT_INTERRUPTS
112 	const struct gpio_dt_spec alert_gpio;
113 #endif /* CONFIG_TMP108_ALERT_INTERRUPTS */
114 };
115 
116 struct tmp108_data {
117 	int16_t sample;
118 
119 	bool one_shot_mode;
120 
121 #ifdef CONFIG_TMP108_ALERT_INTERRUPTS
122 	const struct device *tmp108_dev;
123 
124 	const struct sensor_trigger *temp_alert_trigger;
125 	sensor_trigger_handler_t temp_alert_handler;
126 
127 	struct gpio_callback temp_alert_gpio_cb;
128 #endif /* CONFIG_TMP108_ALERT_INTERRUPTS */
129 };
130 
131 int tmp_108_trigger_set(const struct device *dev,
132 			const struct sensor_trigger *trig,
133 			sensor_trigger_handler_t handler);
134 
135 int tmp108_reg_read(const struct device *dev, uint8_t reg, uint16_t *val);
136 
137 int ti_tmp108_read_temp(const struct device *dev);
138 void tmp108_trigger_handle_one_shot(struct k_work *work);
139 void tmp108_trigger_handle_alert(const struct device *port,
140 				 struct gpio_callback *cb,
141 				 gpio_port_pins_t pins);
142 
143 #endif /*  ZEPHYR_DRIVERS_SENSOR_TMP108_TMP108_H_ */
144