xref: /optee_os/core/include/drivers/i2c.h (revision 19a31ec40245ae01a9adcd206eec2a4bb4479fc9)
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * Copyright (c) 2022, Microchip
4  */
5 
6 #ifndef __DRIVERS_I2C_H
7 #define __DRIVERS_I2C_H
8 
9 #include <kernel/dt_driver.h>
10 #include <libfdt.h>
11 #include <tee_api_types.h>
12 
13 /**
14  * DEFINE_I2C_DEV_DRIVER - Declare an I2C driver
15  *
16  * @__name: I2C device driver name
17  * @__match_table: match table associated to the driver
18  * @__i2c_probe: I2C probe function with the following prototype:
19  *	TEE_Result (*probe)(struct i2c_dev *i2c_dev, const void *fdt,
20  *			    int node, const void *compat_data);
21  */
22 #define DEFINE_I2C_DEV_DRIVER(__name, __match_table, __i2c_probe) \
23 	static TEE_Result __name ## _probe_i2c_dev(const void *fdt, int node, \
24 						   const void *compat_data) \
25 	{ \
26 		struct i2c_dev *i2c_dev = NULL; \
27 		TEE_Result res = TEE_ERROR_GENERIC; \
28 		\
29 		res = i2c_dt_get_dev(fdt, node, &i2c_dev); \
30 		if (res) \
31 			return res; \
32 		return __i2c_probe(i2c_dev, fdt, node, compat_data); \
33 	} \
34 	DEFINE_DT_DRIVER(__name ## _dt_driver) = { \
35 		.name = # __name, \
36 		.type = DT_DRIVER_I2C, \
37 		.match_table = __match_table, \
38 		.probe = __name ## _probe_i2c_dev, \
39 	}
40 
41 #define I2C_SMBUS_MAX_BUF_SIZE	32
42 
43 enum i2c_smbus_dir {
44 	I2C_SMBUS_READ,
45 	I2C_SMBUS_WRITE,
46 };
47 
48 enum i2c_smbus_protocol {
49 	I2C_SMBUS_PROTO_BYTE,
50 	/*
51 	 * Like block but does not insert "count" in sent data, useful for
52 	 * EEPROM read for instance which is not SMBus but requires such
53 	 * sequence.
54 	 */
55 	I2C_SMBUS_PROTO_BLOCK_RAW,
56 };
57 
58 struct i2c_ctrl;
59 
60 /**
61  * struct i2c_dev - I2C device
62  *
63  * @ctrl: I2C controller associated to the device
64  * @addr: device address on the I2C bus
65  */
66 struct i2c_dev {
67 	struct i2c_ctrl *ctrl;
68 	uint16_t addr;
69 };
70 
71 /**
72  * struct i2c_ctrl_ops - Operations provided by I2C controller drivers
73  *
74  * @read: I2C read operation
75  * @write: I2C write operation
76  * @smbus: SMBus protocol operation
77  */
78 struct i2c_ctrl_ops {
79 	TEE_Result (*read)(struct i2c_dev *i2c_dev, uint8_t *buf, size_t len);
80 	TEE_Result (*write)(struct i2c_dev *i2c_dev, const uint8_t *buf,
81 			    size_t len);
82 	TEE_Result (*smbus)(struct i2c_dev *i2c_dev, enum i2c_smbus_dir dir,
83 			    enum i2c_smbus_protocol proto, uint8_t cmd_code,
84 			    uint8_t *buf, size_t len);
85 };
86 
87 /**
88  * struct i2c_ctrl - I2C controller
89  *
90  * @ops: Operations associated to the I2C controller
91  */
92 struct i2c_ctrl {
93 	const struct i2c_ctrl_ops *ops;
94 };
95 
96 #ifdef CFG_DRIVERS_I2C
97 /**
98  * i2c_create_dev - Create and i2c_dev struct from device-tree
99  *
100  * @i2c_ctrl: Controller to be used with this device
101  * @fdt: Device-tree to work on
102  * @node: Node to work on in @fdt provided device-tree
103  *
104  * Return an i2c_dev struct filled from device-tree description
105  */
106 struct i2c_dev *i2c_create_dev(struct i2c_ctrl *i2c_ctrl, const void *fdt,
107 			       int node);
108 
109 /**
110  * i2c_write() - Execute an I2C write on the I2C bus
111  *
112  * @i2c_dev: I2C device used for writing
113  * @buf: Buffer of data to be written
114  * @len: Length of data to be written
115  *
116  * Return a TEE_Result compliant value
117  */
118 static inline TEE_Result i2c_write(struct i2c_dev *i2c_dev, const uint8_t *buf,
119 				   size_t len)
120 {
121 	if (!i2c_dev->ctrl->ops->write)
122 		return TEE_ERROR_NOT_SUPPORTED;
123 
124 	return i2c_dev->ctrl->ops->write(i2c_dev, buf, len);
125 }
126 
127 /**
128  * i2c_read() - Execute an I2C read on the I2C bus
129  *
130  * @i2c_dev: I2C device used for reading
131  * @buf: Buffer containing the read data
132  * @len: Length of data to be read
133  *
134  * Return a TEE_Result compliant value
135  */
136 static inline TEE_Result i2c_read(struct i2c_dev *i2c_dev, uint8_t *buf,
137 				  size_t len)
138 {
139 	if (!i2c_dev->ctrl->ops->read)
140 		return TEE_ERROR_NOT_SUPPORTED;
141 
142 	return i2c_dev->ctrl->ops->read(i2c_dev, buf, len);
143 }
144 
145 /**
146  * i2c_smbus_raw() - Execute a raw SMBUS request
147  *
148  * @i2c_dev: I2C device used for SMBus operation
149  * @dir: Direction for the SMBus transfer
150  * @proto: SMBus Protocol to be executed
151  * @cmd_code: Command code
152  * @buf: Buffer used for read/write operation
153  * @len: Length of buffer to be read/write
154  *
155  * Return a TEE_Result compliant value
156  */
157 static inline TEE_Result i2c_smbus_raw(struct i2c_dev *i2c_dev,
158 				       enum i2c_smbus_dir dir,
159 				       enum i2c_smbus_protocol proto,
160 				       uint8_t cmd_code, uint8_t *buf,
161 				       size_t len)
162 {
163 	if (!i2c_dev->ctrl->ops->smbus)
164 		return TEE_ERROR_NOT_SUPPORTED;
165 
166 	if (len > I2C_SMBUS_MAX_BUF_SIZE)
167 		return TEE_ERROR_BAD_PARAMETERS;
168 
169 	return i2c_dev->ctrl->ops->smbus(i2c_dev, dir, proto, cmd_code, buf,
170 					 len);
171 }
172 
173 /**
174  * i2c_dt_get_dev - Get an I2C device from a DT node
175  *
176  * @fdt: Device tree to work on
177  * @nodeoffset: Node offset of the I2C bus consumer
178  * @i2c_dev: Output I2C bus device upon success
179  *
180  * Return TEE_SUCCESS in case of success
181  * Return TEE_ERROR_DEFER_DRIVER_INIT if I2C controller is not initialized
182  * Return TEE_ERROR_ITEM_NOT_FOUND if the I2C controller node does not exist
183  * Return a TEE_Result compliant code in case of error
184  */
185 static inline TEE_Result i2c_dt_get_dev(const void *fdt, int nodeoffset,
186 					struct i2c_dev **out_i2c_dev)
187 {
188 	TEE_Result res = TEE_ERROR_GENERIC;
189 	void *i2c_dev = NULL;
190 
191 	res = dt_driver_device_from_parent(fdt, nodeoffset, DT_DRIVER_I2C,
192 					   &i2c_dev);
193 	if (!res)
194 		*out_i2c_dev = i2c_dev;
195 
196 	return res;
197 }
198 #else
199 static inline TEE_Result i2c_write(struct i2c_dev *i2c_dev __unused,
200 				   const uint8_t *buf __unused,
201 				   size_t len __unused)
202 {
203 	return TEE_ERROR_NOT_SUPPORTED;
204 }
205 
206 static inline TEE_Result i2c_read(struct i2c_dev *i2c_dev __unused,
207 				  uint8_t *buf __unused, size_t len __unused)
208 {
209 	return TEE_ERROR_NOT_SUPPORTED;
210 }
211 
212 static inline TEE_Result i2c_smbus_raw(struct i2c_dev *i2c_dev __unused,
213 				       enum i2c_smbus_dir dir __unused,
214 				       enum i2c_smbus_protocol proto __unused,
215 				       uint8_t cmd_code __unused,
216 				       uint8_t *buf __unused,
217 				       size_t len __unused)
218 {
219 	return TEE_ERROR_NOT_SUPPORTED;
220 }
221 
222 static inline TEE_Result i2c_dt_get_dev(const void *fdt __unused,
223 					int nodeoffset __unused,
224 					struct i2c_dev **i2c_dev __unused)
225 {
226 	return TEE_ERROR_NOT_SUPPORTED;
227 }
228 #endif
229 
230 /**
231  * i2c_dt_get_func - Typedef of function to get I2C bus device from
232  * devicetree properties
233  *
234  * @args: Pointer to devicetree description of the I2C bus device to parse
235  * @data: Pointer to data given at i2c_dt_register_provider() call
236  * @out_device: Output pointer to I2C device upon success
237  */
238 typedef TEE_Result (*i2c_dt_get_func)(struct dt_pargs *args, void *data,
239 				      struct i2c_dev **out_device);
240 
241 /**
242  * i2c_dt_register_provider - Register a I2C controller provider and add all the
243  *	child nodes of this controller in the DT probe list.
244  *
245  * @fdt: Device tree to work on
246  * @nodeoffset: Node offset of the I2C controller
247  * @get_dt_i2c: Callback to match the I2C controller with a struct i2c
248  * @data: Data which will be passed to the get_dt_i2c callback
249  * Returns TEE_Result value
250  */
251 static inline TEE_Result i2c_register_provider(const void *fdt, int nodeoffset,
252 					       i2c_dt_get_func get_dt_i2c,
253 					       void *data)
254 {
255 	int subnode = -1;
256 	TEE_Result res = TEE_ERROR_GENERIC;
257 
258 	res = dt_driver_register_provider(fdt, nodeoffset,
259 					  (get_of_device_func)get_dt_i2c,
260 					  data, DT_DRIVER_I2C);
261 	if (res)
262 		return res;
263 
264 	fdt_for_each_subnode(subnode, fdt, nodeoffset)
265 		dt_driver_maybe_add_probe_node(fdt, subnode);
266 
267 	return TEE_SUCCESS;
268 }
269 
270 /**
271  * i2c_smbus_read_byte_data() - Execute a read byte SMBus protocol operation
272  *
273  * @i2c_dev: I2C device used for SMBus operation
274  * @cmd_code: Command code to read
275  * @byte: Returned byte value read from device
276  *
277  * Return a TEE_Result compliant value
278  */
279 static inline TEE_Result i2c_smbus_read_byte_data(struct i2c_dev *i2c_dev,
280 						  uint8_t cmd_code,
281 						  uint8_t *byte)
282 {
283 	return i2c_smbus_raw(i2c_dev, I2C_SMBUS_READ, I2C_SMBUS_PROTO_BYTE,
284 			     cmd_code, byte, 1);
285 }
286 
287 /**
288  * i2c_smbus_write_byte_data() - Execute a write byte SMBus protocol operation
289  *
290  * @i2c_dev: I2C device used for SMBus operation
291  * @cmd_code: Command code for write operation
292  * @byte: Byte to be written to the device
293  *
294  * Return a TEE_Result compliant value
295  */
296 static inline TEE_Result i2c_smbus_write_byte_data(struct i2c_dev *i2c_dev,
297 						   uint8_t cmd_code,
298 						   uint8_t byte)
299 {
300 	return i2c_smbus_raw(i2c_dev, I2C_SMBUS_WRITE, I2C_SMBUS_PROTO_BYTE,
301 			     cmd_code, &byte, 1);
302 }
303 
304 /**
305  * i2c_bus_read_block_raw() - Execute a non-standard SMBus raw block read.
306  * This does not insert the "count" of byte to be written unlike the SMBus block
307  * read operation.
308  *
309  * @i2c_dev: I2C device used for SMBus operation
310  * @cmd_code: Command code for read operation
311  * @buf: Buffer of data read from device
312  * @len: Length of data to be read from the device
313  *
314  * Return a TEE_Result compliant value
315  */
316 static inline TEE_Result i2c_bus_read_block_raw(struct i2c_dev *i2c_dev,
317 						uint8_t cmd_code, uint8_t *buf,
318 						size_t len)
319 {
320 	return i2c_smbus_raw(i2c_dev, I2C_SMBUS_READ, I2C_SMBUS_PROTO_BLOCK_RAW,
321 			     cmd_code, buf, len);
322 }
323 
324 /**
325  * i2c_bus_write_block_raw() - Execute a non-standard SMBus raw block write.
326  * This does not insert the "count" of byte to be written unlike the SMBus block
327  * write operation.
328  *
329  * @i2c_dev: I2C device used for SMBus operation
330  * @cmd_code: Command code for write operation
331  * @buf: Buffer of data to be written to the device
332  * @len: Length of data to be written to the device
333  *
334  * Return a TEE_Result compliant value
335  */
336 static inline TEE_Result i2c_bus_write_block_raw(struct i2c_dev *i2c_dev,
337 						 uint8_t cmd_code,
338 						 uint8_t *buf, size_t len)
339 {
340 	return i2c_smbus_raw(i2c_dev, I2C_SMBUS_WRITE,
341 			     I2C_SMBUS_PROTO_BLOCK_RAW, cmd_code, buf, len);
342 }
343 
344 #endif
345