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 */
i2c_write(struct i2c_dev * i2c_dev,const uint8_t * buf,size_t len)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 */
i2c_read(struct i2c_dev * i2c_dev,uint8_t * buf,size_t len)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 */
i2c_smbus_raw(struct i2c_dev * i2c_dev,enum i2c_smbus_dir dir,enum i2c_smbus_protocol proto,uint8_t cmd_code,uint8_t * buf,size_t len)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 */
i2c_dt_get_dev(const void * fdt,int nodeoffset,struct i2c_dev ** out_i2c_dev)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
i2c_write(struct i2c_dev * i2c_dev __unused,const uint8_t * buf __unused,size_t len __unused)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
i2c_read(struct i2c_dev * i2c_dev __unused,uint8_t * buf __unused,size_t len __unused)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
i2c_smbus_raw(struct i2c_dev * i2c_dev __unused,enum i2c_smbus_dir dir __unused,enum i2c_smbus_protocol proto __unused,uint8_t cmd_code __unused,uint8_t * buf __unused,size_t len __unused)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
i2c_dt_get_dev(const void * fdt __unused,int nodeoffset __unused,struct i2c_dev ** i2c_dev __unused)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 */
i2c_register_provider(const void * fdt,int nodeoffset,i2c_dt_get_func get_dt_i2c,void * data)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 */
i2c_smbus_read_byte_data(struct i2c_dev * i2c_dev,uint8_t cmd_code,uint8_t * byte)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 */
i2c_smbus_write_byte_data(struct i2c_dev * i2c_dev,uint8_t cmd_code,uint8_t byte)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 */
i2c_bus_read_block_raw(struct i2c_dev * i2c_dev,uint8_t cmd_code,uint8_t * buf,size_t len)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 */
i2c_bus_write_block_raw(struct i2c_dev * i2c_dev,uint8_t cmd_code,uint8_t * buf,size_t len)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