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