1 /* 2 * Copyright (c) 2023 Google LLC 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #define DT_DRV_COMPAT fintek_f75303 8 9 #include <zephyr/device.h> 10 #include <zephyr/drivers/i2c.h> 11 #include <zephyr/drivers/sensor.h> 12 #include <zephyr/pm/device.h> 13 #include <zephyr/pm/device_runtime.h> 14 #include <zephyr/logging/log.h> 15 #include <zephyr/drivers/sensor/f75303.h> 16 #include "f75303.h" 17 18 #define F75303_SAMPLE_INT_SHIFT 3 19 #define F75303_SAMPLE_FRAC_MASK GENMASK(2, 0) 20 #define F75303_SAMPLE_MICROCELSIUS_PER_BIT 125000 21 22 LOG_MODULE_REGISTER(F75303, CONFIG_SENSOR_LOG_LEVEL); 23 f75303_fetch(const struct i2c_dt_spec * i2c,uint8_t off_h,uint8_t off_l,uint16_t * sample)24 static int f75303_fetch(const struct i2c_dt_spec *i2c, 25 uint8_t off_h, uint8_t off_l, uint16_t *sample) 26 { 27 uint8_t val_h; 28 uint8_t val_l; 29 int res; 30 31 res = i2c_reg_read_byte_dt(i2c, off_h, &val_h); 32 if (res) { 33 return res; 34 } 35 36 res = i2c_reg_read_byte_dt(i2c, off_l, &val_l); 37 if (res) { 38 return res; 39 } 40 41 *sample = val_h << 3 | val_l >> 5; 42 43 return 0; 44 } 45 f75303_fetch_local(const struct device * dev)46 static int f75303_fetch_local(const struct device *dev) 47 { 48 struct f75303_data *data = dev->data; 49 const struct f75303_config *config = dev->config; 50 51 return f75303_fetch(&config->i2c, 52 F75303_LOCAL_TEMP_H, 53 F75303_LOCAL_TEMP_L, 54 &data->sample_local); 55 } 56 f75303_fetch_remote1(const struct device * dev)57 static int f75303_fetch_remote1(const struct device *dev) 58 { 59 struct f75303_data *data = dev->data; 60 const struct f75303_config *config = dev->config; 61 62 return f75303_fetch(&config->i2c, 63 F75303_REMOTE1_TEMP_H, 64 F75303_REMOTE1_TEMP_L, 65 &data->sample_remote1); 66 } 67 f75303_fetch_remote2(const struct device * dev)68 static int f75303_fetch_remote2(const struct device *dev) 69 { 70 struct f75303_data *data = dev->data; 71 const struct f75303_config *config = dev->config; 72 73 return f75303_fetch(&config->i2c, 74 F75303_REMOTE2_TEMP_H, 75 F75303_REMOTE2_TEMP_L, 76 &data->sample_remote2); 77 } 78 f75303_sample_fetch(const struct device * dev,enum sensor_channel chan)79 static int f75303_sample_fetch(const struct device *dev, 80 enum sensor_channel chan) 81 { 82 enum pm_device_state pm_state; 83 int res; 84 85 (void)pm_device_state_get(dev, &pm_state); 86 if (pm_state != PM_DEVICE_STATE_ACTIVE) { 87 return -EIO; 88 } 89 90 switch ((uint32_t)chan) { 91 case SENSOR_CHAN_ALL: 92 res = f75303_fetch_local(dev); 93 if (res) { 94 break; 95 } 96 res = f75303_fetch_remote1(dev); 97 if (res) { 98 break; 99 } 100 res = f75303_fetch_remote2(dev); 101 break; 102 case SENSOR_CHAN_AMBIENT_TEMP: 103 return f75303_fetch_local(dev); 104 case SENSOR_CHAN_F75303_REMOTE1: 105 return f75303_fetch_remote1(dev); 106 case SENSOR_CHAN_F75303_REMOTE2: 107 return f75303_fetch_remote2(dev); 108 default: 109 return -ENOTSUP; 110 } 111 112 return res; 113 } 114 f75303_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)115 static int f75303_channel_get(const struct device *dev, 116 enum sensor_channel chan, 117 struct sensor_value *val) 118 { 119 struct f75303_data *data = dev->data; 120 uint16_t sample; 121 122 switch ((uint32_t)chan) { 123 case SENSOR_CHAN_AMBIENT_TEMP: 124 sample = data->sample_local; 125 break; 126 case SENSOR_CHAN_F75303_REMOTE1: 127 sample = data->sample_remote1; 128 break; 129 case SENSOR_CHAN_F75303_REMOTE2: 130 sample = data->sample_remote2; 131 break; 132 default: 133 return -ENOTSUP; 134 } 135 136 /* 137 * The reading is given in steps of 0.125 degrees celsius, i.e. the 138 * temperature in degrees celsius is equal to sample / 8. 139 */ 140 val->val1 = sample >> F75303_SAMPLE_INT_SHIFT; 141 val->val2 = (sample & F75303_SAMPLE_FRAC_MASK) * F75303_SAMPLE_MICROCELSIUS_PER_BIT; 142 143 return 0; 144 } 145 146 static DEVICE_API(sensor, f75303_driver_api) = { 147 .sample_fetch = f75303_sample_fetch, 148 .channel_get = f75303_channel_get, 149 }; 150 f75303_init(const struct device * dev)151 static int f75303_init(const struct device *dev) 152 { 153 const struct f75303_config *config = dev->config; 154 int res = 0; 155 156 if (!i2c_is_ready_dt(&config->i2c)) { 157 LOG_ERR("I2C device not ready"); 158 return -ENODEV; 159 } 160 161 #ifdef CONFIG_PM_DEVICE_RUNTIME 162 pm_device_init_suspended(dev); 163 164 res = pm_device_runtime_enable(dev); 165 if (res) { 166 LOG_ERR("Failed to enable runtime power management"); 167 } 168 #endif 169 170 return res; 171 } 172 173 #ifdef CONFIG_PM_DEVICE f75303_pm_action(const struct device * dev,enum pm_device_action action)174 static int f75303_pm_action(const struct device *dev, enum pm_device_action action) 175 { 176 switch (action) { 177 case PM_DEVICE_ACTION_TURN_ON: 178 case PM_DEVICE_ACTION_RESUME: 179 case PM_DEVICE_ACTION_TURN_OFF: 180 case PM_DEVICE_ACTION_SUSPEND: 181 return 0; 182 default: 183 return -ENOTSUP; 184 } 185 } 186 #endif 187 188 #define F75303_INST(inst) \ 189 static struct f75303_data f75303_data_##inst; \ 190 static const struct f75303_config f75303_config_##inst = { \ 191 .i2c = I2C_DT_SPEC_INST_GET(inst), \ 192 }; \ 193 PM_DEVICE_DT_INST_DEFINE(inst, f75303_pm_action); \ 194 SENSOR_DEVICE_DT_INST_DEFINE(inst, f75303_init, PM_DEVICE_DT_INST_GET(inst), \ 195 &f75303_data_##inst, &f75303_config_##inst, POST_KERNEL, \ 196 CONFIG_SENSOR_INIT_PRIORITY, &f75303_driver_api); 197 198 DT_INST_FOREACH_STATUS_OKAY(F75303_INST) 199