1 /*
2  * Copyright (c) 2022 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_DRIVERS_SMBUS_H_
8 #define ZEPHYR_INCLUDE_DRIVERS_SMBUS_H_
9 
10 /**
11  * @brief SMBus Interface
12  * @defgroup smbus_interface SMBus Interface
13  * @ingroup io_interfaces
14  * @{
15  */
16 
17 #include <zephyr/types.h>
18 #include <zephyr/device.h>
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 /**
25  * @name SMBus Protocol commands
26  * @{
27  *
28  * SMBus Specification defines the following SMBus protocols operations
29  */
30 
31 /**
32  * SMBus Quick protocol is a very simple command with no data sent or
33  * received. Peripheral may denote only R/W bit, which can still be
34  * used for the peripheral management, for example to switch peripheral
35  * On/Off. Quick protocol can also be used for peripheral devices
36  * scanning.
37  *
38  * @code
39  * 0                   1
40  * 0 1 2 3 4 5 6 7 8 9 0
41  * +-+-+-+-+-+-+-+-+-+-+-+
42  * |S| Periph Addr |D|A|P|
43  * +-+-+-+-+-+-+-+-+-+-+-+
44  * @endcode
45  */
46 #define SMBUS_CMD_QUICK			0b000
47 
48 /**
49  * SMBus Byte protocol can send or receive one byte of data.
50  *
51  * @code
52  * Byte Write
53  *
54  * 0                   1                   2
55  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
56  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57  * |S| Periph Addr |W|A| Command code  |A|P|
58  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59  *
60  * Byte Read
61  *
62  * 0                   1                   2
63  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
64  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65  * |S| Periph Addr |R|A| Byte received |N|P|
66  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
67  * @endcode
68  */
69 #define SMBUS_CMD_BYTE			0b001
70 
71 /**
72  * SMBus Byte Data protocol sends the first byte (command) followed
73  * by read or write one byte.
74  *
75  * @code
76  * Byte Data Write
77  *
78  * 0                   1                   2
79  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8
80  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
81  * |S| Periph Addr |W|A|  Command code |A|   Data Write  |A|P|
82  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83  *
84  * Byte Data Read
85  *
86  * 0                   1                   2
87  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8
88  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
89  * |S| Periph Addr |W|A|  Command code |A|S| Periph Addr |R|A|
90  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
91  * |   Data Read   |N|P|
92  * +-+-+-+-+-+-+-+-+-+-+
93  * @endcode
94  */
95 #define SMBUS_CMD_BYTE_DATA		0b010
96 
97 /**
98  * SMBus Word Data protocol sends the first byte (command) followed
99  * by read or write two bytes.
100  *
101  * @code
102  * Word Data Write
103  *
104  * 0                   1                   2
105  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
106  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107  * |S| Periph Addr |W|A|  Command code |A| Data Write Low|A|
108  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
109  * | Data Write Hi |A|P|
110  * +-+-+-+-+-+-+-+-+-+-+
111  *
112  * Word Data Read
113  *
114  * 0                   1                   2
115  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
116  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
117  * |S| Periph Addr |W|A|  Command code |A|S| Periph Addr |R|
118  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119  * |A| Data Read Low |A|  Data Read Hi |N|P|
120  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
121  * @endcode
122  */
123 #define SMBUS_CMD_WORD_DATA		0b011
124 
125 /**
126  * SMBus Process Call protocol is Write Word followed by
127  * Read Word. It is named so because the command sends data and waits
128  * for the peripheral to return a reply.
129  *
130  * @code
131  * 0                   1                   2
132  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
133  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
134  * |S| Periph Addr |W|A|  Command code |A| Data Write Low|A|
135  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
136  * | Data Write Hi |A|S| Periph Addr |R|A| Data Read Low |A|
137  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
138  * | Data Read Hi  |N|P|
139  * +-+-+-+-+-+-+-+-+-+-+
140  * @endcode
141  */
142 #define SMBUS_CMD_PROC_CALL		0b100
143 
144 /**
145  * SMBus Block protocol reads or writes a block of data up to 32 bytes.
146  * The Count byte specifies the amount of data.
147  *
148  * @code
149  *
150  * SMBus Block Write
151  *
152  * 0                   1                   2
153  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
154  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
155  * |S| Periph Addr |W|A|  Command code |A| Send Count=N  |A|
156  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
157  * |  Data Write 1 |A|      ...      |A|  Data Write N |A|P|
158  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
159  *
160  * SMBus Block Read
161  *
162  * 0                   1                   2
163  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
164  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
165  * |S| Periph Addr |W|A|  Command code |A|S| Periph Addr |R|
166  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
167  * |A|  Recv Count=N |A|  Data Read 1  |A|      ...      |A|
168  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
169  * |  Data Read N  |N|P|
170  * +-+-+-+-+-+-+-+-+-+-+
171  * @endcode
172  */
173 #define SMBUS_CMD_BLOCK			0b101
174 
175 /**
176  * SMBus Block Write - Block Read Process Call protocol is
177  * Block Write followed by Block Read.
178  *
179  * @code
180  * 0                   1                   2
181  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
182  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
183  * |S| Periph Addr |W|A|  Command code |A|   Count = N   |A|
184  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
185  * |  Data Write 1 |A|      ...      |A|  Data Write N |A|S|
186  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
187  * | Periph Addr |R|A|  Recv Count=N |A|  Data Read 1  |A| |
188  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
189  * |     ...     |A|  Data Read N  |N|P|
190  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
191  * @endcode
192  */
193 #define SMBUS_CMD_BLOCK_PROC		0b111
194 /** @} */
195 
196 /** Maximum number of bytes in SMBus Block protocol */
197 #define SMBUS_BLOCK_BYTES_MAX		32
198 
199 /**
200  * @name SMBus device functionality
201  * @{
202  *
203  * The following parameters describe the functionality of the SMBus device
204  */
205 
206 /** Peripheral to act as Controller. */
207 #define SMBUS_MODE_CONTROLLER		BIT(0)
208 
209 /** Support Packet Error Code (PEC) checking */
210 #define SMBUS_MODE_PEC			BIT(1)
211 
212 /** Support Host Notify functionality */
213 #define SMBUS_MODE_HOST_NOTIFY		BIT(2)
214 
215 /** Support SMBALERT signal functionality */
216 #define SMBUS_MODE_SMBALERT		BIT(3)
217 
218 /** @} */
219 
220 /**
221  * @name SMBus special reserved addresses
222  * @{
223  *
224  * The following addresses are reserved by SMBus specification
225  */
226 
227 /**
228  * @brief Alert Response Address (ARA)
229  *
230  * A broadcast address used by the system host as part of the
231  * Alert Response Protocol.
232  */
233 #define SMBUS_ADDRESS_ARA		0x0c
234 
235 /** @} */
236 
237 /**
238  * @name SMBus read / write direction
239  * @{
240  */
241 
242 /** @brief SMBus read / write direction */
243 enum smbus_direction {
244 	/** Write a message to SMBus peripheral */
245 	SMBUS_MSG_WRITE = 0,
246 	/** Read a message from SMBus peripheral */
247 	SMBUS_MSG_READ = 1,
248 };
249 
250 /** @} */
251 
252 /** @cond INTERNAL_HIDDEN */
253 #define SMBUS_MSG_RW_MASK		BIT(0)
254 /** @endcond  */
255 
256 struct smbus_callback;
257 
258 /**
259  * @brief Define SMBus callback handler function signature.
260  *
261  * @param dev Pointer to the device structure for the SMBus driver instance.
262  * @param cb Structure smbus_callback owning this handler.
263  * @param addr Address of the SMBus peripheral device.
264  */
265 typedef void (*smbus_callback_handler_t)(const struct device *dev,
266 					 struct smbus_callback *cb,
267 					 uint8_t addr);
268 
269 /**
270  * @brief SMBus callback structure
271  *
272  * Used to register a callback in the driver instance callback list.
273  * As many callbacks as needed can be added as long as each of them
274  * is a unique pointer of struct smbus_callback.
275  *
276  * Note: Such struct should not be allocated on stack.
277  */
278 struct smbus_callback {
279 	/** This should be used in driver for a callback list management */
280 	sys_snode_t node;
281 
282 	/** Actual callback function being called when relevant */
283 	smbus_callback_handler_t handler;
284 
285 	/** Peripheral device address */
286 	uint8_t addr;
287 };
288 
289 /**
290  * @brief Complete SMBus DT information
291  */
292 struct smbus_dt_spec {
293 	/** SMBus bus */
294 	const struct device *bus;
295 	/** Address of the SMBus peripheral device */
296 	uint16_t addr;
297 };
298 
299 /**
300  * @brief Structure initializer for smbus_dt_spec from devicetree
301  *
302  * This helper macro expands to a static initializer for a <tt>struct
303  * smbus_dt_spec</tt> by reading the relevant bus and address data from
304  * the devicetree.
305  *
306  * @param node_id Devicetree node identifier for the SMBus device whose
307  *                struct smbus_dt_spec to create an initializer for
308  */
309 #define SMBUS_DT_SPEC_GET(node_id)				\
310 	{							\
311 		.bus = DEVICE_DT_GET(DT_BUS(node_id)),		\
312 		.addr = DT_REG_ADDR(node_id)			\
313 	}
314 
315 /**
316  * @brief Structure initializer for smbus_dt_spec from devicetree instance
317  *
318  * This is equivalent to
319  * <tt>SMBUS_DT_SPEC_GET(DT_DRV_INST(inst))</tt>.
320  *
321  * @param inst Devicetree instance number
322  */
323 #define SMBUS_DT_SPEC_INST_GET(inst) SMBUS_DT_SPEC_GET(DT_DRV_INST(inst))
324 
325 /**
326  * @cond INTERNAL_HIDDEN
327  *
328  * These are for internal use only, so skip these in
329  * public documentation.
330  */
331 
332 typedef int (*smbus_api_configure_t)(const struct device *dev,
333 				     uint32_t dev_config);
334 typedef int (*smbus_api_get_config_t)(const struct device *dev,
335 				      uint32_t *dev_config);
336 typedef int (*smbus_api_quick_t)(const struct device *dev,
337 				 uint16_t addr, enum smbus_direction);
338 typedef int (*smbus_api_byte_write_t)(const struct device *dev,
339 				      uint16_t addr, uint8_t byte);
340 typedef int (*smbus_api_byte_read_t)(const struct device *dev,
341 				     uint16_t addr, uint8_t *byte);
342 typedef int (*smbus_api_byte_data_write_t)(const struct device *dev,
343 					   uint16_t addr, uint8_t cmd,
344 					   uint8_t byte);
345 typedef int (*smbus_api_byte_data_read_t)(const struct device *dev,
346 					  uint16_t addr, uint8_t cmd,
347 					  uint8_t *byte);
348 typedef int (*smbus_api_word_data_write_t)(const struct device *dev,
349 					   uint16_t addr, uint8_t cmd,
350 					   uint16_t word);
351 typedef int (*smbus_api_word_data_read_t)(const struct device *dev,
352 					  uint16_t addr, uint8_t cmd,
353 					  uint16_t *word);
354 typedef int (*smbus_api_pcall_t)(const struct device *dev,
355 				 uint16_t addr, uint8_t cmd,
356 				 uint16_t send_word, uint16_t *recv_word);
357 typedef int (*smbus_api_block_write_t)(const struct device *dev,
358 				       uint16_t addr, uint8_t cmd,
359 				       uint8_t count, uint8_t *buf);
360 typedef int (*smbus_api_block_read_t)(const struct device *dev,
361 				      uint16_t addr, uint8_t cmd,
362 				      uint8_t *count, uint8_t *buf);
363 typedef int (*smbus_api_block_pcall_t)(const struct device *dev,
364 				       uint16_t addr, uint8_t cmd,
365 				       uint8_t send_count, uint8_t *send_buf,
366 				       uint8_t *recv_count, uint8_t *recv_buf);
367 typedef int (*smbus_api_smbalert_cb_t)(const struct device *dev,
368 				       struct smbus_callback *cb);
369 typedef int (*smbus_api_host_notify_cb_t)(const struct device *dev,
370 					  struct smbus_callback *cb);
371 
372 __subsystem struct smbus_driver_api {
373 	smbus_api_configure_t configure;
374 	smbus_api_get_config_t get_config;
375 	smbus_api_quick_t smbus_quick;
376 	smbus_api_byte_write_t smbus_byte_write;
377 	smbus_api_byte_read_t smbus_byte_read;
378 	smbus_api_byte_data_write_t smbus_byte_data_write;
379 	smbus_api_byte_data_read_t smbus_byte_data_read;
380 	smbus_api_word_data_write_t smbus_word_data_write;
381 	smbus_api_word_data_read_t smbus_word_data_read;
382 	smbus_api_pcall_t smbus_pcall;
383 	smbus_api_block_write_t smbus_block_write;
384 	smbus_api_block_read_t smbus_block_read;
385 	smbus_api_block_pcall_t smbus_block_pcall;
386 	smbus_api_smbalert_cb_t smbus_smbalert_set_cb;
387 	smbus_api_smbalert_cb_t smbus_smbalert_remove_cb;
388 	smbus_api_host_notify_cb_t smbus_host_notify_set_cb;
389 	smbus_api_host_notify_cb_t smbus_host_notify_remove_cb;
390 };
391 
392 /**
393  * @endcond
394  */
395 
396 #if defined(CONFIG_SMBUS_STATS) || defined(__DOXYGEN__)
397 
398 #include <zephyr/stats/stats.h>
399 
400 /** @cond INTERNAL_HIDDEN */
401 
402 STATS_SECT_START(smbus)
403 STATS_SECT_ENTRY32(bytes_read)
404 STATS_SECT_ENTRY32(bytes_written)
405 STATS_SECT_ENTRY32(command_count)
406 STATS_SECT_END;
407 
408 STATS_NAME_START(smbus)
409 STATS_NAME(smbus, bytes_read)
410 STATS_NAME(smbus, bytes_written)
411 STATS_NAME(smbus, command_count)
412 STATS_NAME_END(smbus);
413 
414 struct smbus_device_state {
415 	struct device_state devstate;
416 	struct stats_smbus stats;
417 };
418 
419 /**
420  * @brief Define a statically allocated and section assigned smbus device state
421  */
422 #define Z_SMBUS_DEVICE_STATE_DEFINE(node_id, dev_name)			\
423 	static struct smbus_device_state Z_DEVICE_STATE_NAME(dev_name)	\
424 	__attribute__((__section__(".z_devstate")));
425 
426 /**
427  * @brief Define an smbus device init wrapper function
428  *
429  * This does device instance specific initialization of common data
430  * (such as stats) and calls the given init_fn
431  */
432 #define Z_SMBUS_INIT_FN(dev_name, init_fn)				\
433 	static inline int						\
434 		UTIL_CAT(dev_name, _init)(const struct device *dev)	\
435 	{								\
436 		struct smbus_device_state *state =			\
437 			CONTAINER_OF(dev->state,			\
438 				     struct smbus_device_state,		\
439 				     devstate);				\
440 		stats_init(&state->stats.s_hdr, STATS_SIZE_32, 4,	\
441 			   STATS_NAME_INIT_PARMS(smbus));		\
442 		stats_register(dev->name, &(state->stats.s_hdr));	\
443 		return init_fn(dev);					\
444 	}
445 
446 /** @endcond */
447 
448 /**
449  * @brief Updates the SMBus stats
450  *
451  * @param dev Pointer to the device structure for the SMBus driver instance
452  * to update stats for.
453  * @param sent Number of bytes sent
454  * @param recv Number of bytes received
455  */
smbus_xfer_stats(const struct device * dev,uint8_t sent,uint8_t recv)456 static inline void smbus_xfer_stats(const struct device *dev, uint8_t sent,
457 				    uint8_t recv)
458 {
459 	struct smbus_device_state *state =
460 		CONTAINER_OF(dev->state, struct smbus_device_state, devstate);
461 
462 	STATS_INC(state->stats, command_count);
463 	STATS_INCN(state->stats, bytes_read, recv);
464 	STATS_INCN(state->stats, bytes_written, sent);
465 }
466 
467 /**
468  * @brief Like DEVICE_DT_DEFINE() with SMBus specifics.
469  *
470  * @details Defines a device which implements the SMBus API. May
471  * generate a custom device_state container struct and init_fn
472  * wrapper when needed depending on SMBus @kconfig{CONFIG_SMBUS_STATS}.
473  *
474  * @param node_id The devicetree node identifier.
475  *
476  * @param init_fn Name of the init function of the driver.
477  *
478  * @param pm_device PM device resources reference
479  * (NULL if device does not use PM).
480  *
481  * @param data_ptr Pointer to the device's private data.
482  *
483  * @param cfg_ptr The address to the structure containing the
484  * configuration information for this instance of the driver.
485  *
486  * @param level The initialization level. See SYS_INIT() for
487  * details.
488  *
489  * @param prio Priority within the selected initialization level. See
490  * SYS_INIT() for details.
491  *
492  * @param api_ptr Provides an initial pointer to the API function struct
493  * used by the driver. Can be NULL.
494  */
495 #define SMBUS_DEVICE_DT_DEFINE(node_id, init_fn, pm_device,		\
496 			       data_ptr, cfg_ptr, level, prio,		\
497 			       api_ptr, ...)				\
498 	Z_SMBUS_DEVICE_STATE_DEFINE(node_id,				\
499 				    Z_DEVICE_DT_DEV_NAME(node_id));	\
500 	Z_SMBUS_INIT_FN(Z_DEVICE_DT_DEV_NAME(node_id), init_fn)		\
501 	Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_NAME(node_id),		\
502 			DEVICE_DT_NAME(node_id),			\
503 			&UTIL_CAT(Z_DEVICE_DT_DEV_NAME(node_id), _init),\
504 			pm_device,					\
505 			data_ptr, cfg_ptr, level, prio,			\
506 			api_ptr,					\
507 			&(Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_NAME	\
508 					      (node_id)).devstate),	\
509 			__VA_ARGS__)
510 
511 #else /* CONFIG_SMBUS_STATS */
512 
smbus_xfer_stats(const struct device * dev,uint8_t sent,uint8_t recv)513 static inline void smbus_xfer_stats(const struct device *dev, uint8_t sent,
514 				    uint8_t recv)
515 {
516 	ARG_UNUSED(dev);
517 	ARG_UNUSED(sent);
518 	ARG_UNUSED(recv);
519 }
520 
521 #define SMBUS_DEVICE_DT_DEFINE(node_id, init_fn, pm_device,		\
522 			     data_ptr, cfg_ptr, level, prio,		\
523 			     api_ptr, ...)				\
524 	DEVICE_DT_DEFINE(node_id, &init_fn, pm_device,			\
525 			     data_ptr, cfg_ptr, level, prio,		\
526 			     api_ptr, __VA_ARGS__)
527 
528 #endif /* CONFIG_SMBUS_STATS */
529 
530 /**
531  * @brief Like SMBUS_DEVICE_DT_DEFINE() for an instance of a DT_DRV_COMPAT
532  * compatible
533  *
534  * @param inst instance number. This is replaced by
535  * <tt>DT_DRV_COMPAT(inst)</tt> in the call to SMBUS_DEVICE_DT_DEFINE().
536  *
537  * @param ... other parameters as expected by SMBUS_DEVICE_DT_DEFINE().
538  */
539 #define SMBUS_DEVICE_DT_INST_DEFINE(inst, ...)		\
540 	SMBUS_DEVICE_DT_DEFINE(DT_DRV_INST(inst), __VA_ARGS__)
541 
542 /**
543  * @brief Configure operation of a SMBus host controller.
544  *
545  * @param dev Pointer to the device structure for the SMBus driver instance.
546  * @param dev_config Bit-packed 32-bit value to the device runtime configuration
547  * for the SMBus controller.
548  *
549  * @retval 0 If successful.
550  * @retval -EIO General input / output error.
551  */
552 __syscall int smbus_configure(const struct device *dev, uint32_t dev_config);
553 
z_impl_smbus_configure(const struct device * dev,uint32_t dev_config)554 static inline int z_impl_smbus_configure(const struct device *dev,
555 					 uint32_t dev_config)
556 {
557 	const struct smbus_driver_api *api =
558 		(const struct smbus_driver_api *)dev->api;
559 
560 	return api->configure(dev, dev_config);
561 }
562 
563 /**
564  * @brief Get configuration of a SMBus host controller.
565  *
566  * This routine provides a way to get current configuration. It is allowed to
567  * call the function before smbus_configure, because some SMBus ports can be
568  * configured during init process. However, if the SMBus port is not configured,
569  * smbus_get_config returns an error.
570  *
571  * smbus_get_config can return cached config or probe hardware, but it has to be
572  * up to date with current configuration.
573  *
574  * @param dev Pointer to the device structure for the SMBus driver instance.
575  * @param dev_config Pointer to return bit-packed 32-bit value of
576  * the SMBus controller configuration.
577  *
578  * @retval 0 If successful.
579  * @retval -EIO General input / output error.
580  * @retval -ENOSYS If function smbus_get_config() is not implemented
581  * by the driver.
582  */
583 __syscall int smbus_get_config(const struct device *dev, uint32_t *dev_config);
584 
z_impl_smbus_get_config(const struct device * dev,uint32_t * dev_config)585 static inline int z_impl_smbus_get_config(const struct device *dev,
586 					  uint32_t *dev_config)
587 {
588 	const struct smbus_driver_api *api =
589 		(const struct smbus_driver_api *)dev->api;
590 
591 	if (api->get_config == NULL) {
592 		return -ENOSYS;
593 	}
594 
595 	return api->get_config(dev, dev_config);
596 }
597 
598 /**
599  * @brief Add SMBUSALERT callback for a SMBus host controller.
600  *
601  * @param dev Pointer to the device structure for the SMBus driver instance.
602  * @param cb Pointer to a callback structure.
603  *
604  * @retval 0 If successful.
605  * @retval -EIO General input / output error.
606  * @retval -ENOSYS If function smbus_smbalert_set_cb() is not implemented
607  * by the driver.
608  */
609 __syscall int smbus_smbalert_set_cb(const struct device *dev,
610 				    struct smbus_callback *cb);
611 
z_impl_smbus_smbalert_set_cb(const struct device * dev,struct smbus_callback * cb)612 static inline int z_impl_smbus_smbalert_set_cb(const struct device *dev,
613 					       struct smbus_callback *cb)
614 {
615 	const struct smbus_driver_api *api =
616 		(const struct smbus_driver_api *)dev->api;
617 
618 	if (api->smbus_smbalert_set_cb == NULL) {
619 		return -ENOSYS;
620 	}
621 
622 	return api->smbus_smbalert_set_cb(dev, cb);
623 }
624 
625 /**
626  * @brief Remove SMBUSALERT callback from a SMBus host controller.
627  *
628  * @param dev Pointer to the device structure for the SMBus driver instance.
629  * @param cb Pointer to a callback structure.
630  *
631  * @retval 0 If successful.
632  * @retval -EIO General input / output error.
633  * @retval -ENOSYS If function smbus_smbalert_remove_cb() is not implemented
634  * by the driver.
635  */
636 __syscall int smbus_smbalert_remove_cb(const struct device *dev,
637 				       struct smbus_callback *cb);
638 
z_impl_smbus_smbalert_remove_cb(const struct device * dev,struct smbus_callback * cb)639 static inline int z_impl_smbus_smbalert_remove_cb(const struct device *dev,
640 						  struct smbus_callback *cb)
641 {
642 	const struct smbus_driver_api *api =
643 		(const struct smbus_driver_api *)dev->api;
644 
645 	if (api->smbus_smbalert_remove_cb == NULL) {
646 		return -ENOSYS;
647 	}
648 
649 	return api->smbus_smbalert_remove_cb(dev, cb);
650 }
651 
652 /**
653  * @brief Add Host Notify callback for a SMBus host controller.
654  *
655  * @param dev Pointer to the device structure for the SMBus driver instance.
656  * @param cb Pointer to a callback structure.
657  *
658  * @retval 0 If successful.
659  * @retval -EIO General input / output error.
660  * @retval -ENOSYS If function smbus_host_notify_set_cb() is not implemented
661  * by the driver.
662  */
663 __syscall int smbus_host_notify_set_cb(const struct device *dev,
664 				       struct smbus_callback *cb);
665 
z_impl_smbus_host_notify_set_cb(const struct device * dev,struct smbus_callback * cb)666 static inline int z_impl_smbus_host_notify_set_cb(const struct device *dev,
667 						  struct smbus_callback *cb)
668 {
669 	const struct smbus_driver_api *api =
670 		(const struct smbus_driver_api *)dev->api;
671 
672 	if (api->smbus_host_notify_set_cb == NULL) {
673 		return -ENOSYS;
674 	}
675 
676 	return api->smbus_host_notify_set_cb(dev, cb);
677 }
678 
679 /**
680  * @brief Remove Host Notify callback from a SMBus host controller.
681  *
682  * @param dev Pointer to the device structure for the SMBus driver instance.
683  * @param cb Pointer to a callback structure.
684  *
685  * @retval 0 If successful.
686  * @retval -EIO General input / output error.
687  * @retval -ENOSYS If function smbus_host_notify_remove_cb() is not implemented
688  * by the driver.
689  */
690 __syscall int smbus_host_notify_remove_cb(const struct device *dev,
691 					  struct smbus_callback *cb);
692 
z_impl_smbus_host_notify_remove_cb(const struct device * dev,struct smbus_callback * cb)693 static inline int z_impl_smbus_host_notify_remove_cb(const struct device *dev,
694 						     struct smbus_callback *cb)
695 {
696 	const struct smbus_driver_api *api =
697 		(const struct smbus_driver_api *)dev->api;
698 
699 	if (api->smbus_host_notify_remove_cb == NULL) {
700 		return -ENOSYS;
701 	}
702 
703 	return api->smbus_host_notify_remove_cb(dev, cb);
704 }
705 
706 /**
707  * @brief Perform SMBus Quick operation
708  *
709  * This routine provides a generic interface to perform SMBus Quick
710  * operation.
711  *
712  * @param dev Pointer to the device structure for the SMBus driver instance.
713  * driver configured in controller mode.
714  * @param addr Address of the SMBus peripheral device.
715  * @param direction Direction Read or Write.
716  *
717  * @retval 0 If successful.
718  * @retval -EIO General input / output error.
719  * @retval -ENOSYS If function smbus_quick() is not implemented
720  * by the driver.
721  */
722 __syscall int smbus_quick(const struct device *dev, uint16_t addr,
723 			  enum smbus_direction direction);
724 
z_impl_smbus_quick(const struct device * dev,uint16_t addr,enum smbus_direction direction)725 static inline int z_impl_smbus_quick(const struct device *dev, uint16_t addr,
726 				     enum smbus_direction direction)
727 {
728 	const struct smbus_driver_api *api =
729 		(const struct smbus_driver_api *)dev->api;
730 
731 	if (api->smbus_quick == NULL) {
732 		return -ENOSYS;
733 	}
734 
735 	if (direction != SMBUS_MSG_READ && direction != SMBUS_MSG_WRITE) {
736 		return -EINVAL;
737 	}
738 
739 	return  api->smbus_quick(dev, addr, direction);
740 }
741 
742 /**
743  * @brief Perform SMBus Byte Write operation
744  *
745  * This routine provides a generic interface to perform SMBus
746  * Byte Write operation.
747  *
748  * @param dev Pointer to the device structure for the SMBus driver instance.
749  * @param addr Address of the SMBus peripheral device.
750  * @param byte Byte to be sent to the peripheral device.
751  *
752  * @retval 0 If successful.
753  * @retval -EIO General input / output error.
754  * @retval -ENOSYS If function smbus_byte_write() is not implemented
755  * by the driver.
756  */
757 __syscall int smbus_byte_write(const struct device *dev, uint16_t addr,
758 			       uint8_t byte);
759 
z_impl_smbus_byte_write(const struct device * dev,uint16_t addr,uint8_t byte)760 static inline int z_impl_smbus_byte_write(const struct device *dev,
761 					  uint16_t addr, uint8_t byte)
762 {
763 	const struct smbus_driver_api *api =
764 		(const struct smbus_driver_api *)dev->api;
765 
766 	if (api->smbus_byte_write == NULL) {
767 		return -ENOSYS;
768 	}
769 
770 	return  api->smbus_byte_write(dev, addr, byte);
771 }
772 
773 /**
774  * @brief Perform SMBus Byte Read operation
775  *
776  * This routine provides a generic interface to perform SMBus
777  * Byte Read operation.
778  *
779  * @param dev Pointer to the device structure for the SMBus driver instance.
780  * @param addr Address of the SMBus peripheral device.
781  * @param byte Byte received from the peripheral device.
782  *
783  * @retval 0 If successful.
784  * @retval -EIO General input / output error.
785  * @retval -ENOSYS If function smbus_byte_read() is not implemented
786  * by the driver.
787  */
788 __syscall int smbus_byte_read(const struct device *dev, uint16_t addr,
789 			      uint8_t *byte);
790 
z_impl_smbus_byte_read(const struct device * dev,uint16_t addr,uint8_t * byte)791 static inline int z_impl_smbus_byte_read(const struct device *dev,
792 					 uint16_t addr, uint8_t *byte)
793 {
794 	const struct smbus_driver_api *api =
795 		(const struct smbus_driver_api *)dev->api;
796 
797 	if (api->smbus_byte_read == NULL) {
798 		return -ENOSYS;
799 	}
800 
801 	return  api->smbus_byte_read(dev, addr, byte);
802 }
803 
804 /**
805  * @brief Perform SMBus Byte Data Write operation
806  *
807  * This routine provides a generic interface to perform SMBus
808  * Byte Data Write operation.
809  *
810  * @param dev Pointer to the device structure for the SMBus driver instance.
811  * @param addr Address of the SMBus peripheral device.
812  * @param cmd Command byte which is sent to peripheral device first.
813  * @param byte Byte to be sent to the peripheral device.
814  *
815  * @retval 0 If successful.
816  * @retval -EIO General input / output error.
817  * @retval -ENOSYS If function smbus_byte_data_write() is not implemented
818  * by the driver.
819  */
820 __syscall int smbus_byte_data_write(const struct device *dev, uint16_t addr,
821 				    uint8_t cmd, uint8_t byte);
822 
z_impl_smbus_byte_data_write(const struct device * dev,uint16_t addr,uint8_t cmd,uint8_t byte)823 static inline int z_impl_smbus_byte_data_write(const struct device *dev,
824 					       uint16_t addr, uint8_t cmd,
825 					       uint8_t byte)
826 {
827 	const struct smbus_driver_api *api =
828 		(const struct smbus_driver_api *)dev->api;
829 
830 	if (api->smbus_byte_data_write == NULL) {
831 		return -ENOSYS;
832 	}
833 
834 	return  api->smbus_byte_data_write(dev, addr, cmd, byte);
835 }
836 
837 /**
838  * @brief Perform SMBus Byte Data Read operation
839  *
840  * This routine provides a generic interface to perform SMBus
841  * Byte Data Read operation.
842  *
843  * @param dev Pointer to the device structure for the SMBus driver instance.
844  * @param addr Address of the SMBus peripheral device.
845  * @param cmd Command byte which is sent to peripheral device first.
846  * @param byte Byte received from the peripheral device.
847  *
848  * @retval 0 If successful.
849  * @retval -EIO General input / output error.
850  * @retval -ENOSYS If function smbus_byte_data_read() is not implemented
851  * by the driver.
852  */
853 __syscall int smbus_byte_data_read(const struct device *dev, uint16_t addr,
854 				   uint8_t cmd, uint8_t *byte);
855 
z_impl_smbus_byte_data_read(const struct device * dev,uint16_t addr,uint8_t cmd,uint8_t * byte)856 static inline int z_impl_smbus_byte_data_read(const struct device *dev,
857 					      uint16_t addr, uint8_t cmd,
858 					      uint8_t *byte)
859 {
860 	const struct smbus_driver_api *api =
861 		(const struct smbus_driver_api *)dev->api;
862 
863 	if (api->smbus_byte_data_read == NULL) {
864 		return -ENOSYS;
865 	}
866 
867 	return  api->smbus_byte_data_read(dev, addr, cmd, byte);
868 }
869 
870 /**
871  * @brief Perform SMBus Word Data Write operation
872  *
873  * This routine provides a generic interface to perform SMBus
874  * Word Data Write operation.
875  *
876  * @param dev Pointer to the device structure for the SMBus driver instance.
877  * @param addr Address of the SMBus peripheral device.
878  * @param cmd Command byte which is sent to peripheral device first.
879  * @param word Word (16-bit) to be sent to the peripheral device.
880  *
881  * @retval 0 If successful.
882  * @retval -EIO General input / output error.
883  * @retval -ENOSYS If function smbus_word_data_write() is not implemented
884  * by the driver.
885  */
886 __syscall int smbus_word_data_write(const struct device *dev, uint16_t addr,
887 				    uint8_t cmd, uint16_t word);
888 
z_impl_smbus_word_data_write(const struct device * dev,uint16_t addr,uint8_t cmd,uint16_t word)889 static inline int z_impl_smbus_word_data_write(const struct device *dev,
890 					       uint16_t addr, uint8_t cmd,
891 					       uint16_t word)
892 {
893 	const struct smbus_driver_api *api =
894 		(const struct smbus_driver_api *)dev->api;
895 
896 	if (api->smbus_word_data_write == NULL) {
897 		return -ENOSYS;
898 	}
899 
900 	return  api->smbus_word_data_write(dev, addr, cmd, word);
901 }
902 
903 /**
904  * @brief Perform SMBus Word Data Read operation
905  *
906  * This routine provides a generic interface to perform SMBus
907  * Word Data Read operation.
908  *
909  * @param dev Pointer to the device structure for the SMBus driver instance.
910  * @param addr Address of the SMBus peripheral device.
911  * @param cmd Command byte which is sent to peripheral device first.
912  * @param word Word (16-bit) received from the peripheral device.
913  *
914  * @retval 0 If successful.
915  * @retval -EIO General input / output error.
916  * @retval -ENOSYS If function smbus_word_data_read() is not implemented
917  * by the driver.
918  */
919 __syscall int smbus_word_data_read(const struct device *dev, uint16_t addr,
920 				   uint8_t cmd, uint16_t *word);
921 
z_impl_smbus_word_data_read(const struct device * dev,uint16_t addr,uint8_t cmd,uint16_t * word)922 static inline int z_impl_smbus_word_data_read(const struct device *dev,
923 					      uint16_t addr, uint8_t cmd,
924 					      uint16_t *word)
925 {
926 	const struct smbus_driver_api *api =
927 		(const struct smbus_driver_api *)dev->api;
928 
929 	if (api->smbus_word_data_read == NULL) {
930 		return -ENOSYS;
931 	}
932 
933 	return  api->smbus_word_data_read(dev, addr, cmd, word);
934 }
935 
936 /**
937  * @brief Perform SMBus Process Call operation
938  *
939  * This routine provides a generic interface to perform SMBus
940  * Process Call operation, which means Write 2 bytes following by
941  * Read 2 bytes.
942  *
943  * @param dev Pointer to the device structure for the SMBus driver instance.
944  * @param addr Address of the SMBus peripheral device.
945  * @param cmd Command byte which is sent to peripheral device first.
946  * @param send_word Word (16-bit) to be sent to the peripheral device.
947  * @param recv_word Word (16-bit) received from the peripheral device.
948  *
949  * @retval 0 If successful.
950  * @retval -EIO General input / output error.
951  * @retval -ENOSYS If function smbus_pcall() is not implemented
952  * by the driver.
953  */
954 __syscall int smbus_pcall(const struct device *dev, uint16_t addr,
955 			  uint8_t cmd, uint16_t send_word, uint16_t *recv_word);
956 
z_impl_smbus_pcall(const struct device * dev,uint16_t addr,uint8_t cmd,uint16_t send_word,uint16_t * recv_word)957 static inline int z_impl_smbus_pcall(const struct device *dev,
958 				     uint16_t addr, uint8_t cmd,
959 				     uint16_t send_word, uint16_t *recv_word)
960 {
961 	const struct smbus_driver_api *api =
962 		(const struct smbus_driver_api *)dev->api;
963 
964 	if (api->smbus_pcall == NULL) {
965 		return -ENOSYS;
966 	}
967 
968 	return  api->smbus_pcall(dev, addr, cmd, send_word, recv_word);
969 }
970 
971 /**
972  * @brief Perform SMBus Block Write operation
973  *
974  * This routine provides a generic interface to perform SMBus
975  * Block Write operation.
976  *
977  * @param dev Pointer to the device structure for the SMBus driver instance.
978  * @param addr Address of the SMBus peripheral device.
979  * @param cmd Command byte which is sent to peripheral device first.
980  * @param count Size of the data block buffer. Maximum 32 bytes.
981  * @param buf Data block buffer to be sent to the peripheral device.
982  *
983  * @retval 0 If successful.
984  * @retval -EIO General input / output error.
985  * @retval -ENOSYS If function smbus_block_write() is not implemented
986  * by the driver.
987  */
988 __syscall int smbus_block_write(const struct device *dev, uint16_t addr,
989 				uint8_t cmd, uint8_t count, uint8_t *buf);
990 
z_impl_smbus_block_write(const struct device * dev,uint16_t addr,uint8_t cmd,uint8_t count,uint8_t * buf)991 static inline int z_impl_smbus_block_write(const struct device *dev,
992 					   uint16_t addr, uint8_t cmd,
993 					   uint8_t count, uint8_t *buf)
994 {
995 	const struct smbus_driver_api *api =
996 		(const struct smbus_driver_api *)dev->api;
997 
998 	if (api->smbus_block_write == NULL) {
999 		return -ENOSYS;
1000 	}
1001 
1002 	if (count < 1 || count > SMBUS_BLOCK_BYTES_MAX) {
1003 		return -EINVAL;
1004 	}
1005 
1006 	return  api->smbus_block_write(dev, addr, cmd, count, buf);
1007 }
1008 
1009 /**
1010  * @brief Perform SMBus Block Read operation
1011  *
1012  * This routine provides a generic interface to perform SMBus
1013  * Block Read operation.
1014  *
1015  * @param dev Pointer to the device structure for the SMBus driver instance.
1016  * @param addr Address of the SMBus peripheral device.
1017  * @param cmd Command byte which is sent to peripheral device first.
1018  * @param count Size of the data peripheral sent. Maximum 32 bytes.
1019  * @param buf Data block buffer received from the peripheral device.
1020  *
1021  * @retval 0 If successful.
1022  * @retval -EIO General input / output error.
1023  * @retval -ENOSYS If function smbus_block_read() is not implemented
1024  * by the driver.
1025  */
1026 __syscall int smbus_block_read(const struct device *dev, uint16_t addr,
1027 			       uint8_t cmd, uint8_t *count, uint8_t *buf);
1028 
z_impl_smbus_block_read(const struct device * dev,uint16_t addr,uint8_t cmd,uint8_t * count,uint8_t * buf)1029 static inline int z_impl_smbus_block_read(const struct device *dev,
1030 					  uint16_t addr, uint8_t cmd,
1031 					  uint8_t *count, uint8_t *buf)
1032 {
1033 	const struct smbus_driver_api *api =
1034 		(const struct smbus_driver_api *)dev->api;
1035 
1036 	if (api->smbus_block_read == NULL) {
1037 		return -ENOSYS;
1038 	}
1039 
1040 	return  api->smbus_block_read(dev, addr, cmd, count, buf);
1041 }
1042 
1043 /**
1044  * @brief Perform SMBus Block Process Call operation
1045  *
1046  * This routine provides a generic interface to perform SMBus
1047  * Block Process Call operation. This operation is basically
1048  * Block Write followed by Block Read.
1049  *
1050  * @param dev Pointer to the device structure for the SMBus driver instance.
1051  * @param addr Address of the SMBus peripheral device.
1052  * @param cmd Command byte which is sent to peripheral device first.
1053  * @param snd_count Size of the data block buffer to send.
1054  * @param snd_buf Data block buffer send to the peripheral device.
1055  * @param rcv_count Size of the data peripheral sent.
1056  * @param rcv_buf Data block buffer received from the peripheral device.
1057  *
1058  * @retval 0 If successful.
1059  * @retval -EIO General input / output error.
1060  * @retval -ENOSYS If function smbus_block_pcall() is not implemented
1061  * by the driver.
1062  */
1063 __syscall int smbus_block_pcall(const struct device *dev,
1064 				uint16_t addr, uint8_t cmd,
1065 				uint8_t snd_count, uint8_t *snd_buf,
1066 				uint8_t *rcv_count, uint8_t *rcv_buf);
1067 
z_impl_smbus_block_pcall(const struct device * dev,uint16_t addr,uint8_t cmd,uint8_t snd_count,uint8_t * snd_buf,uint8_t * rcv_count,uint8_t * rcv_buf)1068 static inline int z_impl_smbus_block_pcall(const struct device *dev,
1069 					   uint16_t addr, uint8_t cmd,
1070 					   uint8_t snd_count, uint8_t *snd_buf,
1071 					   uint8_t *rcv_count, uint8_t *rcv_buf)
1072 {
1073 	const struct smbus_driver_api *api =
1074 		(const struct smbus_driver_api *)dev->api;
1075 
1076 	if (api->smbus_block_pcall == NULL) {
1077 		return -ENOSYS;
1078 	}
1079 
1080 	return  api->smbus_block_pcall(dev, addr, cmd, snd_count, snd_buf,
1081 				       rcv_count, rcv_buf);
1082 }
1083 
1084 #ifdef __cplusplus
1085 }
1086 #endif
1087 
1088 /**
1089  * @}
1090  */
1091 
1092 #include <syscalls/smbus.h>
1093 
1094 #endif /* ZEPHYR_INCLUDE_DRIVERS_SMBUS_H_ */
1095