1 /*
2 * Copyright (c) 2020 Christian Hirsch
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #define DT_DRV_COMPAT maxim_max31855
7
8 #include <zephyr/kernel.h>
9 #include <zephyr/drivers/sensor.h>
10 #include <zephyr/init.h>
11 #include <zephyr/drivers/gpio.h>
12 #include <zephyr/sys/byteorder.h>
13 #include <zephyr/sys/__assert.h>
14 #include <zephyr/drivers/spi.h>
15 #include <zephyr/logging/log.h>
16 #include <zephyr/types.h>
17 #include <zephyr/device.h>
18
19 #define THERMOCOUPLE_TEMPERATURE_POS 18
20 #define INTERNAL_TEMPERATURE_POS 4
21 #define THERMOCOUPLE_SIGN_BITS 0xffff2000
22 #define INTERNAL_SIGN_BITS 0xfffff800
23 #define THERMOCOUPLE_RESOLUTION 25
24 #define INTERNAL_RESOLUTION 625
25
26 LOG_MODULE_REGISTER(MAX31855, CONFIG_SENSOR_LOG_LEVEL);
27
28 struct max31855_config {
29 struct spi_dt_spec spi;
30 };
31
32 struct max31855_data {
33 uint32_t sample;
34 };
35
max31855_sample_fetch(const struct device * dev,enum sensor_channel chan)36 static int max31855_sample_fetch(const struct device *dev, enum sensor_channel chan)
37 {
38 struct max31855_data *data = dev->data;
39 const struct max31855_config *config = dev->config;
40 int ret;
41
42 __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL);
43
44 struct spi_buf rx_buf = {
45 .buf = &(data->sample),
46 .len = sizeof(data->sample),
47 };
48 const struct spi_buf_set rx = {.buffers = &rx_buf, .count = 1};
49
50 ret = spi_read_dt(&config->spi, &rx);
51 if (ret < 0) {
52 LOG_ERR("max31855_read FAIL %d", ret);
53 return ret;
54 }
55
56 return 0;
57 }
58
max31855_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)59 static int max31855_channel_get(const struct device *dev, enum sensor_channel chan,
60 struct sensor_value *val)
61 {
62 struct max31855_data *data = dev->data;
63 uint32_t temp = sys_be32_to_cpu(data->sample);
64
65 if (temp & BIT(16)) {
66 return -EIO;
67 }
68
69 switch (chan) {
70
71 case SENSOR_CHAN_AMBIENT_TEMP:
72 temp = (temp >> THERMOCOUPLE_TEMPERATURE_POS) & 0x3fff;
73
74 /* if sign bit is set, make value negative */
75 if (temp & BIT(14)) {
76 temp |= THERMOCOUPLE_SIGN_BITS;
77 }
78
79 temp = temp * THERMOCOUPLE_RESOLUTION;
80
81 val->val1 = temp / 100;
82 val->val2 = (temp - val->val1 * 100) * 10000;
83 break;
84
85 case SENSOR_CHAN_DIE_TEMP:
86 temp = (temp >> INTERNAL_TEMPERATURE_POS) & 0xfff;
87
88 /* if sign bit is set, make value negative */
89 if (temp & BIT(12)) {
90 temp |= INTERNAL_SIGN_BITS;
91 }
92
93 temp = temp * INTERNAL_RESOLUTION;
94
95 val->val1 = temp / 10000;
96 val->val2 = (temp - val->val1 * 10000) * 100;
97 break;
98
99 default:
100 return -ENOTSUP;
101 }
102
103 return 0;
104 }
105
106 static DEVICE_API(sensor, max31855_api) = {
107 .sample_fetch = max31855_sample_fetch,
108 .channel_get = max31855_channel_get,
109 };
110
max31855_init(const struct device * dev)111 static int max31855_init(const struct device *dev)
112 {
113 const struct max31855_config *config = dev->config;
114
115 if (!spi_is_ready_dt(&config->spi)) {
116 LOG_ERR("SPI bus is not ready");
117 return -ENODEV;
118 }
119
120 return 0;
121 }
122
123 #define MAX31855_INIT(n) \
124 static struct max31855_data max31855_data_##n; \
125 static const struct max31855_config max31855_config_##n = { \
126 .spi = SPI_DT_SPEC_INST_GET(n, SPI_OP_MODE_MASTER | SPI_WORD_SET(8U), 0U), \
127 }; \
128 SENSOR_DEVICE_DT_INST_DEFINE(n, &max31855_init, NULL, &max31855_data_##n, \
129 &max31855_config_##n, POST_KERNEL, \
130 CONFIG_SENSOR_INIT_PRIORITY, &max31855_api);
131
132 DT_INST_FOREACH_STATUS_OKAY(MAX31855_INIT)
133