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