xref: /illumos-gate/usr/src/test/i2c-tests/i2csimd/i2csimd_ts511x.c (revision 0cbe48189888d02563dba9c90132ac391ba233b6)
1*0cbe4818SRobert Mustacchi /*
2*0cbe4818SRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*0cbe4818SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*0cbe4818SRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*0cbe4818SRobert Mustacchi  * 1.0 of the CDDL.
6*0cbe4818SRobert Mustacchi  *
7*0cbe4818SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*0cbe4818SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*0cbe4818SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*0cbe4818SRobert Mustacchi  */
11*0cbe4818SRobert Mustacchi 
12*0cbe4818SRobert Mustacchi /*
13*0cbe4818SRobert Mustacchi  * Copyright 2025 Oxide Computer Company
14*0cbe4818SRobert Mustacchi  */
15*0cbe4818SRobert Mustacchi 
16*0cbe4818SRobert Mustacchi /*
17*0cbe4818SRobert Mustacchi  * Minimally emulate a TS5111. We use a basic register template for this. We
18*0cbe4818SRobert Mustacchi  * allow a minimum number of writable registers, but that doesn't change
19*0cbe4818SRobert Mustacchi  * behavior for anything. We will ignore any attempts to go to I3C mode or to
20*0cbe4818SRobert Mustacchi  * change the default read address mode and starting point.
21*0cbe4818SRobert Mustacchi  */
22*0cbe4818SRobert Mustacchi 
23*0cbe4818SRobert Mustacchi #include <stdlib.h>
24*0cbe4818SRobert Mustacchi #include <string.h>
25*0cbe4818SRobert Mustacchi #include <err.h>
26*0cbe4818SRobert Mustacchi #include <sys/sysmacros.h>
27*0cbe4818SRobert Mustacchi #include <sys/bitext.h>
28*0cbe4818SRobert Mustacchi 
29*0cbe4818SRobert Mustacchi #include "i2csimd.h"
30*0cbe4818SRobert Mustacchi 
31*0cbe4818SRobert Mustacchi #define	TS5111_REGLEN	256
32*0cbe4818SRobert Mustacchi 
33*0cbe4818SRobert Mustacchi typedef struct ts5111 {
34*0cbe4818SRobert Mustacchi 	uint8_t ts_data[TS5111_REGLEN];
35*0cbe4818SRobert Mustacchi 	uint8_t ts_curaddr;
36*0cbe4818SRobert Mustacchi } ts5111_t;
37*0cbe4818SRobert Mustacchi 
38*0cbe4818SRobert Mustacchi /*
39*0cbe4818SRobert Mustacchi  * Default register values from the spec, ignoring what we're going to set for
40*0cbe4818SRobert Mustacchi  * the temperature when this is created.
41*0cbe4818SRobert Mustacchi  */
42*0cbe4818SRobert Mustacchi static const uint8_t ts5111_tmpl[TS5111_REGLEN] = {
43*0cbe4818SRobert Mustacchi 	[0x00] = 0x51,
44*0cbe4818SRobert Mustacchi 	[0x01] = 0x11,
45*0cbe4818SRobert Mustacchi 	[0x02] = 0x12,
46*0cbe4818SRobert Mustacchi 	[0x03] = 0x00,
47*0cbe4818SRobert Mustacchi 	[0x04] = 0x01,
48*0cbe4818SRobert Mustacchi 	[0x07] = 0x0e,
49*0cbe4818SRobert Mustacchi 	[0x28] = 0x70,
50*0cbe4818SRobert Mustacchi 	[0x29] = 0x03,
51*0cbe4818SRobert Mustacchi 	[0x32] = 0x50,
52*0cbe4818SRobert Mustacchi 	[0x33] = 0x05
53*0cbe4818SRobert Mustacchi };
54*0cbe4818SRobert Mustacchi 
55*0cbe4818SRobert Mustacchi /*
56*0cbe4818SRobert Mustacchi  * While we could emulate and support writes for a subset of the device space
57*0cbe4818SRobert Mustacchi  * that's writable, we just discard everything other than setting the current
58*0cbe4818SRobert Mustacchi  * address because we don't need it.
59*0cbe4818SRobert Mustacchi  */
60*0cbe4818SRobert Mustacchi static bool
ts5111_write(void * arg,uint32_t len,const uint8_t * buf)61*0cbe4818SRobert Mustacchi ts5111_write(void *arg, uint32_t len, const uint8_t *buf)
62*0cbe4818SRobert Mustacchi {
63*0cbe4818SRobert Mustacchi 	ts5111_t *ts = arg;
64*0cbe4818SRobert Mustacchi 
65*0cbe4818SRobert Mustacchi 	if (len > 0) {
66*0cbe4818SRobert Mustacchi 		ts->ts_curaddr = buf[0];
67*0cbe4818SRobert Mustacchi 	}
68*0cbe4818SRobert Mustacchi 
69*0cbe4818SRobert Mustacchi 	return (true);
70*0cbe4818SRobert Mustacchi }
71*0cbe4818SRobert Mustacchi 
72*0cbe4818SRobert Mustacchi /*
73*0cbe4818SRobert Mustacchi  * If someone reads past the end of the device, we just wrap to the start.
74*0cbe4818SRobert Mustacchi  */
75*0cbe4818SRobert Mustacchi static bool
ts5111_read(void * arg,uint32_t len,uint8_t * buf)76*0cbe4818SRobert Mustacchi ts5111_read(void *arg, uint32_t len, uint8_t *buf)
77*0cbe4818SRobert Mustacchi {
78*0cbe4818SRobert Mustacchi 	ts5111_t *ts = arg;
79*0cbe4818SRobert Mustacchi 
80*0cbe4818SRobert Mustacchi 	while (len > 0) {
81*0cbe4818SRobert Mustacchi 		uint16_t rem = sizeof (ts->ts_data) - ts->ts_curaddr + 1;
82*0cbe4818SRobert Mustacchi 		uint16_t toread = MIN(rem, len);
83*0cbe4818SRobert Mustacchi 
84*0cbe4818SRobert Mustacchi 		(void) memcpy(buf, &ts->ts_data[ts->ts_curaddr], toread);
85*0cbe4818SRobert Mustacchi 		buf += toread;
86*0cbe4818SRobert Mustacchi 		len -= toread;
87*0cbe4818SRobert Mustacchi 		ts->ts_curaddr += toread;
88*0cbe4818SRobert Mustacchi 	}
89*0cbe4818SRobert Mustacchi 
90*0cbe4818SRobert Mustacchi 	return (true);
91*0cbe4818SRobert Mustacchi }
92*0cbe4818SRobert Mustacchi 
93*0cbe4818SRobert Mustacchi static const i2csimd_ops_t ts5111_ops = {
94*0cbe4818SRobert Mustacchi 	.sop_write = ts5111_write,
95*0cbe4818SRobert Mustacchi 	.sop_read = ts5111_read
96*0cbe4818SRobert Mustacchi };
97*0cbe4818SRobert Mustacchi 
98*0cbe4818SRobert Mustacchi i2csimd_dev_t *
i2csimd_make_ts5111(uint8_t addr,uint16_t temp)99*0cbe4818SRobert Mustacchi i2csimd_make_ts5111(uint8_t addr, uint16_t temp)
100*0cbe4818SRobert Mustacchi {
101*0cbe4818SRobert Mustacchi 	ts5111_t *ts = calloc(1, sizeof (ts5111_t));
102*0cbe4818SRobert Mustacchi 	if (ts == NULL) {
103*0cbe4818SRobert Mustacchi 		err(EXIT_FAILURE, "failed to allocate a ts5111_t");
104*0cbe4818SRobert Mustacchi 	}
105*0cbe4818SRobert Mustacchi 
106*0cbe4818SRobert Mustacchi 	(void) memcpy(ts->ts_data, ts5111_tmpl, sizeof (ts5111_tmpl));
107*0cbe4818SRobert Mustacchi 	ts->ts_data[0x31] = bitx16(temp, 7, 0);
108*0cbe4818SRobert Mustacchi 	ts->ts_data[0x32] = bitx16(temp, 15, 8);
109*0cbe4818SRobert Mustacchi 
110*0cbe4818SRobert Mustacchi 	i2csimd_dev_t *dev = calloc(1, sizeof (i2csimd_dev_t));
111*0cbe4818SRobert Mustacchi 	if (dev == NULL) {
112*0cbe4818SRobert Mustacchi 		err(EXIT_FAILURE, "failed to allocate i2csimd_dev_t");
113*0cbe4818SRobert Mustacchi 	}
114*0cbe4818SRobert Mustacchi 
115*0cbe4818SRobert Mustacchi 	dev->dev_name = "ts5111";
116*0cbe4818SRobert Mustacchi 	dev->dev_addr = addr;
117*0cbe4818SRobert Mustacchi 	dev->dev_arg = ts;
118*0cbe4818SRobert Mustacchi 	dev->dev_ops = &ts5111_ops;
119*0cbe4818SRobert Mustacchi 
120*0cbe4818SRobert Mustacchi 	return (dev);
121*0cbe4818SRobert Mustacchi }
122