File indexing completed on 2025-05-11 08:24:11
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifdef HAVE_CONFIG_H
0011 #include "config.h"
0012 #endif
0013
0014 #include <stdio.h>
0015
0016 #include <dev/i2c/i2c.h>
0017 #include <dev/i2c/ti-tmp112.h>
0018
0019
0020
0021
0022 #define TMP_TEMPERATURE (0)
0023 #define TMP_CONFIG (1)
0024 #define TMP_LOW_TEMP (2)
0025 #define TMP_HIGH_TEMP (3)
0026
0027
0028
0029
0030 #define CFG_ONE_SHOT_BASE (15)
0031 #define CFG_SHUTDOWN_BASE (8)
0032 #define CFG_EXTENDED_MODE_BASE (4)
0033
0034 #define CFG_ONE_SHOT (1 << CFG_ONE_SHOT_BASE)
0035 #define CFG_SHUTDOWN (1 << CFG_SHUTDOWN_BASE)
0036 #define CFG_EXTENDED_MODE (1 << CFG_EXTENDED_MODE_BASE)
0037
0038 typedef struct {
0039 i2c_dev base;
0040 uint8_t pointer;
0041 uint16_t config_shadow;
0042 } ti_tmp112;
0043
0044 static int
0045 ti_tmp112_reg_write(ti_tmp112* dev, int reg, uint16_t value)
0046 {
0047 uint8_t out[3];
0048 i2c_msg msgs[1] = {
0049 {
0050 .addr = dev->base.address,
0051 .flags = 0,
0052 .len = (uint16_t) sizeof(out),
0053 .buf = &out[0]
0054 }
0055 };
0056 int err;
0057 if (dev->pointer == reg) {
0058 out[0] = (uint8_t) (value >> 8);
0059 out[1] = (uint8_t) value;
0060 msgs[0].len = 2;
0061 }
0062 else {
0063 out[0] = reg;
0064 out[1] = (uint8_t) (value >> 8);
0065 out[2] = (uint8_t) value;
0066 }
0067 err = i2c_bus_transfer(dev->base.bus, &msgs[0], RTEMS_ARRAY_SIZE(msgs));
0068 if (err == 0)
0069 dev->pointer = reg;
0070 else
0071 dev->pointer = -1;
0072 return err;
0073 }
0074
0075 static int
0076 ti_tmp112_reg_read(ti_tmp112* dev, int reg, uint16_t* value)
0077 {
0078 uint8_t in[2] = { 0, 0 };
0079 int err;
0080 if (dev->pointer == reg) {
0081 i2c_msg msgs[1] = {
0082 {
0083 .addr = dev->base.address,
0084 .flags = I2C_M_RD,
0085 .len = (uint16_t) sizeof(in),
0086 .buf = &in[0]
0087 }
0088 };
0089 err = i2c_bus_transfer(dev->base.bus, &msgs[0], RTEMS_ARRAY_SIZE(msgs));
0090 }
0091 else {
0092 uint8_t out[1] = { (uint8_t) reg };
0093 i2c_msg msgs[2] = {
0094 {
0095 .addr = dev->base.address,
0096 .flags = 0,
0097 .len = (uint16_t) sizeof(out),
0098 .buf = &out[0]
0099 }, {
0100 .addr = dev->base.address,
0101 .flags = I2C_M_RD,
0102 .len = (uint16_t) sizeof(in),
0103 .buf = &in[0]
0104 }
0105 };
0106 err = i2c_bus_transfer(dev->base.bus, &msgs[0], RTEMS_ARRAY_SIZE(msgs));
0107 if (err == 0)
0108 dev->pointer = reg;
0109 else
0110 dev->pointer = -1;
0111 }
0112 *value = (((uint16_t) in[0]) << 8) | in[1];
0113 return err;
0114 }
0115
0116 static int
0117 ti_tmp112_set_config(ti_tmp112* dev, uint16_t value)
0118 {
0119 int err;
0120 dev->config_shadow = value;
0121 err = ti_tmp112_reg_write(dev, TMP_CONFIG, dev->config_shadow);
0122 return err;
0123 }
0124
0125 static int
0126 ti_tmp112_get_temp(ti_tmp112* dev, int* temp, bool raw)
0127 {
0128 uint16_t value = 0;
0129 int err;
0130
0131 *temp = 0;
0132
0133 if ((dev->config_shadow & CFG_SHUTDOWN) == CFG_SHUTDOWN) {
0134 i2c_bus_obtain(dev->base.bus);
0135 err = ti_tmp112_reg_write(dev,
0136 TMP_CONFIG,
0137 dev->config_shadow | CFG_ONE_SHOT);
0138 if (err == 0) {
0139 uint16_t config = 0;
0140 while (err == 0 && (config & CFG_ONE_SHOT) == 0)
0141 err = ti_tmp112_reg_read(dev, TMP_CONFIG, &config);
0142 err = ti_tmp112_reg_read(dev, TMP_TEMPERATURE, &value);
0143 }
0144 i2c_bus_release(dev->base.bus);
0145 }
0146 else {
0147 err = ti_tmp112_reg_read(dev, TMP_TEMPERATURE, &value);
0148 }
0149
0150 if (err == 0) {
0151 if (raw) {
0152 *temp = (int) value;
0153 }
0154 else {
0155 int bits = 12;
0156 uint32_t u;
0157 if ((dev->config_shadow & CFG_EXTENDED_MODE) != 0)
0158 bits = 13;
0159 u = value >> ((sizeof(value) * 8) - bits);
0160 *temp = (int) (u & ((1 << bits) - 1));
0161 if ((u & (1 << (bits - 1))) != 0)
0162 *temp |= ~((1 << bits) - 1);
0163 *temp = *temp * 625;
0164 }
0165 }
0166
0167 return err;
0168 }
0169
0170 static int
0171 ti_tmp112_ioctl(i2c_dev* iic_dev, ioctl_command_t command, void* arg)
0172 {
0173 ti_tmp112* dev = (ti_tmp112*) iic_dev;
0174 uint16_t v16;
0175 int vint;
0176 int err;
0177
0178 switch (command) {
0179 case TI_TMP112_GET_TEMP:
0180 vint = 0;
0181 err = ti_tmp112_get_temp(dev, &vint, false);
0182 if (err == 0)
0183 *((int*) arg) = vint;
0184 break;
0185 case TI_TMP112_GET_TEMP_RAW:
0186 vint = 0;
0187 err = ti_tmp112_get_temp(dev, &vint, true);
0188 if (err == 0)
0189 *((uint16_t*) arg) = (uint16_t) vint;
0190 break;
0191 case TI_TMP112_SET_CONFIG:
0192 v16 = (uint16_t)(uintptr_t) arg;
0193 err = ti_tmp112_set_config(dev, v16);
0194 break;
0195 case TI_TMP112_SET_LOW_TEMP:
0196 v16 = (uint16_t)(uintptr_t) arg;
0197 err = ti_tmp112_reg_write(dev, TMP_LOW_TEMP, v16);
0198 break;
0199 case TI_TMP112_SET_HIGH_TEMP:
0200 v16 = (uint16_t)(uintptr_t) arg;
0201 err = ti_tmp112_reg_write(dev, TMP_HIGH_TEMP, v16);
0202 break;
0203 default:
0204 err = -ENOTTY;
0205 break;
0206 }
0207
0208 return err;
0209 }
0210
0211 int
0212 i2c_dev_register_ti_tmp112(const char* bus_path,
0213 const char* dev_path,
0214 uint16_t address)
0215 {
0216 ti_tmp112* dev;
0217
0218 dev = (ti_tmp112*)
0219 i2c_dev_alloc_and_init(sizeof(*dev), bus_path, address);
0220 if (dev == NULL) {
0221 return -1;
0222 }
0223
0224 dev->base.ioctl = ti_tmp112_ioctl;
0225 dev->pointer = -1;
0226 dev->config_shadow = 0x60a0;
0227
0228 return i2c_dev_register(&dev->base, dev_path);
0229 }