xref: /aosp_15_r20/external/coreboot/tests/device/i2c-test.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/i2c_simple.h>
4 #include <limits.h>
5 #include <tests/test.h>
6 
7 /* Simulate two i2c devices, both on bus 0, each with three uint8_t regs
8    implemented. */
9 typedef struct {
10 	uint8_t reg;
11 	uint8_t data;
12 } i2c_ex_regs_t;
13 
14 typedef struct {
15 	unsigned int bus;
16 	uint8_t slave;
17 	i2c_ex_regs_t regs[3];
18 } i2c_ex_devs_t;
19 
20 i2c_ex_devs_t i2c_ex_devs[] = {
21 	{
22 		.bus = 0,
23 		.slave = 0xA,
24 		.regs = {
25 			{.reg = 0x0, .data = 0xB},
26 			{.reg = 0x1, .data = 0x6},
27 			{.reg = 0x2, .data = 0xF},
28 		}
29 	},
30 	{
31 		.bus = 0,
32 		.slave = 0x3,
33 		.regs = {
34 			{.reg = 0x0, .data = 0xDE},
35 			{.reg = 0x1, .data = 0xAD},
36 			{.reg = 0x2, .data = 0xBE},
37 		}
38 	},
39 };
40 
platform_i2c_transfer(unsigned int bus,struct i2c_msg * segments,int count)41 int platform_i2c_transfer(unsigned int bus, struct i2c_msg *segments, int count)
42 {
43 	int i;
44 	int reg;
45 	struct i2c_msg *tmp = segments;
46 	i2c_ex_devs_t *i2c_dev = NULL;
47 
48 	check_expected(count);
49 
50 	for (i = 0; i < count; i++, segments++) {
51 		check_expected_ptr(segments->buf);
52 		check_expected(segments->flags);
53 	}
54 
55 	reg = tmp->buf[0];
56 
57 	/* Find object for requested device */
58 	for (i = 0; i < ARRAY_SIZE(i2c_ex_devs); i++)
59 		if (i2c_ex_devs[i].slave == tmp->slave) {
60 			i2c_dev = &i2c_ex_devs[i];
61 			break;
62 		}
63 
64 	if (i2c_dev == NULL)
65 		return -1;
66 
67 	/* Write commands */
68 	if (tmp->len > 1) {
69 		i2c_dev->regs[reg].data = tmp->buf[1];
70 	};
71 
72 	/* Read commands */
73 	for (i = 0; i < count; i++, tmp++)
74 		if (tmp->flags & I2C_M_RD) {
75 			*(tmp->buf) = i2c_dev->regs[reg].data;
76 		};
77 
78 	return 0;
79 }
80 
mock_expect_params_platform_i2c_transfer(void)81 static void mock_expect_params_platform_i2c_transfer(void)
82 {
83 	unsigned long int expected_flags[] = {0, I2C_M_RD, I2C_M_TEN, I2C_M_RECV_LEN,
84 					      I2C_M_NOSTART};
85 
86 	/* Flags should always be only within supported range */
87 	expect_in_set_count(platform_i2c_transfer, segments->flags, expected_flags, -1);
88 
89 	expect_not_value_count(platform_i2c_transfer, segments->buf, NULL, -1);
90 
91 	expect_in_range_count(platform_i2c_transfer, count, 1, INT_MAX, -1);
92 }
93 
94 #define MASK 0x3
95 #define SHIFT 0x1
96 
i2c_read_field_test(void ** state)97 static void i2c_read_field_test(void **state)
98 {
99 	int i, j;
100 	uint8_t buf;
101 
102 	mock_expect_params_platform_i2c_transfer();
103 
104 	/* Read particular bits in all registers in all devices, then compare
105 	   with expected value. */
106 	for (i = 0; i < ARRAY_SIZE(i2c_ex_devs); i++)
107 		for (j = 0; j < ARRAY_SIZE(i2c_ex_devs[0].regs); j++) {
108 			i2c_read_field(i2c_ex_devs[i].bus, i2c_ex_devs[i].slave,
109 				       i2c_ex_devs[i].regs[j].reg, &buf, MASK, SHIFT);
110 			assert_int_equal(
111 				(i2c_ex_devs[i].regs[j].data & (MASK << SHIFT)) >> SHIFT, buf);
112 		};
113 
114 	/* Read whole registers */
115 	for (i = 0; i < ARRAY_SIZE(i2c_ex_devs); i++)
116 		for (j = 0; j < ARRAY_SIZE(i2c_ex_devs[0].regs); j++) {
117 			i2c_read_field(i2c_ex_devs[i].bus, i2c_ex_devs[i].slave,
118 				       i2c_ex_devs[i].regs[j].reg, &buf, 0xFF, 0);
119 			assert_int_equal(i2c_ex_devs[i].regs[j].data, buf);
120 		};
121 }
122 
i2c_write_field_test(void ** state)123 static void i2c_write_field_test(void **state)
124 {
125 	int i, j;
126 	uint8_t buf, tmp;
127 
128 	mock_expect_params_platform_i2c_transfer();
129 
130 	/* Clear particular bits in all registers in all devices, then compare
131 	   with expected value. */
132 	for (i = 0; i < ARRAY_SIZE(i2c_ex_devs); i++)
133 		for (j = 0; j < ARRAY_SIZE(i2c_ex_devs[0].regs); j++) {
134 			buf = 0x0;
135 			tmp = i2c_ex_devs[i].regs[j].data;
136 			i2c_write_field(i2c_ex_devs[i].bus, i2c_ex_devs[i].slave,
137 					i2c_ex_devs[i].regs[j].reg, buf, MASK, SHIFT);
138 			assert_int_equal(i2c_ex_devs[i].regs[j].data,
139 					 (tmp & ~(MASK << SHIFT)) | (buf << SHIFT));
140 		};
141 
142 	/* Set all bits in all registers, this time verify using
143 	   i2c_read_field() accessor. */
144 	for (i = 0; i < ARRAY_SIZE(i2c_ex_devs); i++)
145 		for (j = 0; j < ARRAY_SIZE(i2c_ex_devs[0].regs); j++) {
146 			i2c_write_field(i2c_ex_devs[i].bus, i2c_ex_devs[i].slave,
147 					i2c_ex_devs[i].regs[j].reg, 0xFF, 0xFF, 0);
148 			i2c_read_field(i2c_ex_devs[i].bus, i2c_ex_devs[i].slave,
149 				       i2c_ex_devs[i].regs[j].reg, &buf, 0xFF, 0);
150 			assert_int_equal(buf, 0xFF);
151 		};
152 }
153 
main(void)154 int main(void)
155 {
156 	const struct CMUnitTest tests[] = {cmocka_unit_test(i2c_read_field_test),
157 					   cmocka_unit_test(i2c_write_field_test)};
158 
159 	return cb_run_group_tests(tests, NULL, NULL);
160 }
161