Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:11

0001 /*
0002  * Copyright (c) 2016-2017 Chris Johns <chrisj@rtems.org>
0003  * All rights reserved.
0004  *
0005  * The license and distribution terms for this file may be
0006  * found in the file LICENSE in this distribution or at
0007  * http://www.rtems.org/license/LICENSE.
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  * Registers.
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  * Configuration register.
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 }