source: rtems/cpukit/dev/i2c/ti-tmp112.c @ b2ed712

5
Last change on this file since b2ed712 was 849500d, checked in by Chris Johns <chrisj@…>, on 08/16/17 at 05:10:33

dev/i2c: Add I2C device support for FPGA Slave, LM25066A, TMP112, ADS1113, ADS1114 and ADS1115

Closes #3101.

  • Property mode set to 100644
File size: 5.2 KB
Line 
1/*
2 * Copyright (c) 2016-2017 Chris Johns <chrisj@rtems.org>
3 * All rights reserved.
4 *
5 * The license and distribution terms for this file may be
6 * found in the file LICENSE in this distribution or at
7 * http://www.rtems.org/license/LICENSE.
8 */
9
10#if HAVE_CONFIG_H
11  #include "config.h"
12#endif
13
14#include <stdio.h>
15
16#include <dev/i2c/i2c.h>
17#include <dev/i2c/ti-tmp112.h>
18
19/*
20 * Registers.
21 */
22#define TMP_TEMPERATURE (0)
23#define TMP_CONFIG      (1)
24#define TMP_LOW_TEMP    (2)
25#define TMP_HIGH_TEMP   (3)
26
27/*
28 * Configuration register.
29 */
30#define CFG_ONE_SHOT_BASE         (15)
31#define CFG_SHUTDOWN_BASE         (8)
32#define CFG_EXTENDED_MODE_BASE    (4)
33
34#define CFG_ONE_SHOT              (1 << CFG_ONE_SHOT_BASE)
35#define CFG_SHUTDOWN              (1 << CFG_SHUTDOWN_BASE)
36#define CFG_EXTENDED_MODE         (1 << CFG_EXTENDED_MODE_BASE)
37
38typedef struct {
39  i2c_dev  base;
40  uint8_t  pointer;
41  uint16_t config_shadow;
42} ti_tmp112;
43
44static int
45ti_tmp112_reg_write(ti_tmp112* dev, int reg, uint16_t value)
46{
47  uint8_t out[3];
48  i2c_msg msgs[1] = {
49    {
50      .addr = dev->base.address,
51      .flags = 0,
52      .len = (uint16_t) sizeof(out),
53      .buf = &out[0]
54    }
55  };
56  int err;
57  if (dev->pointer == reg) {
58    out[0] = (uint8_t) (value >> 8);
59    out[1] = (uint8_t) value;
60    msgs[0].len = 2;
61  }
62  else {
63    out[0] = reg;
64    out[1] = (uint8_t) (value >> 8);
65    out[2] = (uint8_t) value;
66  }
67  err = i2c_bus_transfer(dev->base.bus, &msgs[0], RTEMS_ARRAY_SIZE(msgs));
68  if (err == 0)
69    dev->pointer = reg;
70  else
71    dev->pointer = -1;
72  return err;
73}
74
75static int
76ti_tmp112_reg_read(ti_tmp112* dev, int reg, uint16_t* value)
77{
78  uint8_t in[2] = { 0, 0 };
79  int     err;
80  if (dev->pointer == reg) {
81    i2c_msg msgs[1] = {
82      {
83        .addr = dev->base.address,
84        .flags = I2C_M_RD,
85        .len = (uint16_t) sizeof(in),
86        .buf = &in[0]
87      }
88    };
89    err = i2c_bus_transfer(dev->base.bus, &msgs[0], RTEMS_ARRAY_SIZE(msgs));
90  }
91  else {
92    uint8_t out[1] = { (uint8_t) reg };
93    i2c_msg msgs[2] = {
94      {
95        .addr = dev->base.address,
96        .flags = 0,
97        .len = (uint16_t) sizeof(out),
98        .buf = &out[0]
99      }, {
100        .addr = dev->base.address,
101        .flags = I2C_M_RD,
102        .len = (uint16_t) sizeof(in),
103        .buf = &in[0]
104      }
105    };
106    err = i2c_bus_transfer(dev->base.bus, &msgs[0], RTEMS_ARRAY_SIZE(msgs));
107    if (err == 0)
108      dev->pointer = reg;
109    else
110      dev->pointer = -1;
111  }
112  *value = (((uint16_t) in[0]) << 8) | in[1];
113  return err;
114}
115
116static int
117ti_tmp112_set_config(ti_tmp112* dev, uint16_t value)
118{
119  int err;
120  dev->config_shadow = value;
121  err = ti_tmp112_reg_write(dev, TMP_CONFIG, dev->config_shadow);
122  return err;
123}
124
125static int
126ti_tmp112_get_temp(ti_tmp112* dev, int* temp, bool raw)
127{
128  uint16_t value = 0;
129  int      err;
130
131  *temp = 0;
132
133  if ((dev->config_shadow & CFG_SHUTDOWN) == CFG_SHUTDOWN) {
134    i2c_bus_obtain(dev->base.bus);
135    err = ti_tmp112_reg_write(dev,
136                           TMP_CONFIG,
137                           dev->config_shadow | CFG_ONE_SHOT);
138    if (err == 0) {
139      uint16_t config = 0;
140      while (err == 0 && (config & CFG_ONE_SHOT) == 0)
141        err = ti_tmp112_reg_read(dev, TMP_CONFIG, &config);
142      err = ti_tmp112_reg_read(dev, TMP_TEMPERATURE, &value);
143    }
144    i2c_bus_release(dev->base.bus);
145  }
146  else {
147    err = ti_tmp112_reg_read(dev, TMP_TEMPERATURE, &value);
148  }
149
150  if (err == 0) {
151    if (raw) {
152      *temp = (int) value;
153    }
154    else {
155      int      bits = 12;
156      uint32_t u;
157      if ((dev->config_shadow & CFG_EXTENDED_MODE) != 0)
158        bits = 13;
159      u = value >> ((sizeof(value) * 8) - bits);
160      *temp = (int) (u  & ((1 << bits) - 1));
161      if ((u & (1 << (bits - 1))) != 0)
162        *temp |= ~((1 << bits) - 1);
163      *temp = *temp * 625;
164    }
165  }
166
167  return err;
168}
169
170static int
171ti_tmp112_ioctl(i2c_dev* iic_dev, ioctl_command_t command, void* arg)
172{
173  ti_tmp112* dev = (ti_tmp112*) iic_dev;
174  uint16_t   v16;
175  int        vint;
176  int        err;
177
178  switch (command) {
179    case TI_TMP112_GET_TEMP:
180      vint = 0;
181      err = ti_tmp112_get_temp(dev, &vint, false);
182      if (err == 0)
183        *((int*) arg) = vint;
184      break;
185    case TI_TMP112_GET_TEMP_RAW:
186      vint = 0;
187      err = ti_tmp112_get_temp(dev, &vint, true);
188      if (err == 0)
189        *((uint16_t*) arg) = (uint16_t) vint;
190      break;
191    case TI_TMP112_SET_CONFIG:
192      v16 = (uint16_t)(uintptr_t) arg;
193      err = ti_tmp112_set_config(dev, v16);
194      break;
195    case TI_TMP112_SET_LOW_TEMP:
196      v16 = (uint16_t)(uintptr_t) arg;
197      err = ti_tmp112_reg_write(dev, TMP_LOW_TEMP, v16);
198      break;
199    case TI_TMP112_SET_HIGH_TEMP:
200      v16 = (uint16_t)(uintptr_t) arg;
201      err = ti_tmp112_reg_write(dev, TMP_HIGH_TEMP, v16);
202      break;
203    default:
204      err = -ENOTTY;
205      break;
206  }
207
208  return err;
209}
210
211int
212i2c_dev_register_ti_tmp112(const char* bus_path,
213                           const char* dev_path,
214                           uint16_t    address)
215{
216  ti_tmp112* dev;
217
218  dev = (ti_tmp112*)
219    i2c_dev_alloc_and_init(sizeof(*dev), bus_path, address);
220  if (dev == NULL) {
221    return -1;
222  }
223
224  dev->base.ioctl = ti_tmp112_ioctl;
225  dev->pointer = -1;
226  dev->config_shadow = 0x60a0;
227
228  return i2c_dev_register(&dev->base, dev_path);
229}
Note: See TracBrowser for help on using the repository browser.