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