Line data Source code
1 0 : /*
2 : * Copyright (c) 2025 STMicroelectronics
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : #ifndef ZEPHYR_INCLUDE_RTIO_REGMAP_H_
8 : #define ZEPHYR_INCLUDE_RTIO_REGMAP_H_
9 :
10 : #include <zephyr/rtio/rtio.h>
11 :
12 : #ifdef __cplusplus
13 : extern "C" {
14 : #endif
15 :
16 : /**
17 : * @brief A structure to describe a list of not-consecutive memory chunks
18 : * for RTIO operations.
19 : */
20 1 : struct rtio_regs {
21 : /** Number of registers in the list **/
22 1 : size_t rtio_regs_num;
23 :
24 0 : struct rtio_regs_list {
25 : /** Register address **/
26 1 : uint8_t reg_addr;
27 :
28 : /** Valid pointer to a data buffer **/
29 1 : uint8_t *bufp;
30 :
31 : /** Length of the buffer in bytes **/
32 1 : size_t len;
33 0 : } *rtio_regs_list;
34 : };
35 :
36 : /**
37 : * @brief bus type
38 : *
39 : * RTIO works on top of a RTIO enabled bus, Some RTIO ops require
40 : * a bus-related handling (e.g. rtio_read_regs_async)
41 : */
42 0 : typedef enum {
43 : RTIO_BUS_I2C,
44 : RTIO_BUS_SPI,
45 : RTIO_BUS_I3C,
46 : } rtio_bus_type;
47 :
48 : /**
49 : * @brief check if bus is SPI
50 : * @param bus_type Type of bus (I2C, SPI, I3C)
51 : * @return true if bus type is SPI
52 : */
53 1 : static inline bool rtio_is_spi(rtio_bus_type bus_type)
54 : {
55 : return (bus_type == RTIO_BUS_SPI);
56 : }
57 :
58 : /**
59 : * @brief check if bus is I2C
60 : * @param bus_type Type of bus (I2C, SPI, I3C)
61 : * @return true if bus type is I2C
62 : */
63 1 : static inline bool rtio_is_i2c(rtio_bus_type bus_type)
64 : {
65 : return (bus_type == RTIO_BUS_I2C);
66 : }
67 :
68 : /**
69 : * @brief check if bus is I3C
70 : * @param bus_type Type of bus (I2C, SPI, I3C)
71 : * @return true if bus type is I3C
72 : */
73 1 : static inline bool rtio_is_i3c(rtio_bus_type bus_type)
74 : {
75 : return (bus_type == RTIO_BUS_I3C);
76 : }
77 :
78 : /*
79 : * @brief Create a chain of SQEs representing a bus transaction to read a reg.
80 : *
81 : * The RTIO-enabled bus driver is instrumented to perform bus read ops
82 : * for each register in the list.
83 : *
84 : * Usage:
85 : *
86 : * @code{.c}
87 : * struct rtio_regs regs;
88 : * struct rtio_reg_list regs_list[] = {{regs_addr1, mem_addr_1, mem_len_1},
89 : * {regs_addr2, mem_addr_2, mem_len_2},
90 : * ...
91 : * };
92 : * regs.rtio_regs_list = regs_list;
93 : * regs.rtio_regs_num = ARRAY_SIZE(regs_list);
94 : *
95 : * rtio_read_regs_async(rtio,
96 : * iodev,
97 : * RTIO_BUS_SPI,
98 : * ®s,
99 : * sqe,
100 : * dev,
101 : * op_cb);
102 : * @endcode
103 : *
104 : * @param r RTIO context
105 : * @param iodev IO device
106 : * @param bus_type Type of bus (I2C, SPI, I3C)
107 : * @param regs pointer to list of registers to be read. Raise proper bit in case of SPI bus
108 : * @param iodev_sqe IODEV submission for the await op
109 : * @param dev pointer to the device structure
110 : * @param complete_op_cb callback routine at the end of op
111 : */
112 0 : static inline void rtio_read_regs_async(struct rtio *r, struct rtio_iodev *iodev,
113 : rtio_bus_type bus_type, struct rtio_regs *regs,
114 : struct rtio_iodev_sqe *iodev_sqe, const struct device *dev,
115 : rtio_callback_t complete_op_cb)
116 : {
117 : struct rtio_sqe *write_addr;
118 : struct rtio_sqe *read_reg;
119 : struct rtio_sqe *complete_op;
120 :
121 : for (uint8_t i = 0; i < regs->rtio_regs_num; i++) {
122 :
123 : write_addr = rtio_sqe_acquire(r);
124 : read_reg = rtio_sqe_acquire(r);
125 :
126 : if (write_addr == NULL || read_reg == NULL) {
127 : rtio_iodev_sqe_err(iodev_sqe, -ENOMEM);
128 : rtio_sqe_drop_all(r);
129 : return;
130 : }
131 :
132 : rtio_sqe_prep_tiny_write(write_addr, iodev, RTIO_PRIO_NORM,
133 : ®s->rtio_regs_list[i].reg_addr, 1, NULL);
134 : write_addr->flags = RTIO_SQE_TRANSACTION;
135 :
136 : rtio_sqe_prep_read(read_reg, iodev, RTIO_PRIO_NORM, regs->rtio_regs_list[i].bufp,
137 : regs->rtio_regs_list[i].len, NULL);
138 : read_reg->flags = RTIO_SQE_CHAINED;
139 :
140 : switch (bus_type) {
141 : case RTIO_BUS_I2C:
142 : read_reg->iodev_flags |= RTIO_IODEV_I2C_STOP | RTIO_IODEV_I2C_RESTART;
143 : break;
144 : case RTIO_BUS_I3C:
145 : read_reg->iodev_flags |= RTIO_IODEV_I3C_STOP | RTIO_IODEV_I3C_RESTART;
146 : break;
147 : case RTIO_BUS_SPI:
148 : default:
149 : break;
150 : }
151 : }
152 :
153 : complete_op = rtio_sqe_acquire(r);
154 : if (complete_op == NULL) {
155 : rtio_iodev_sqe_err(iodev_sqe, -ENOMEM);
156 : rtio_sqe_drop_all(r);
157 : return;
158 : }
159 :
160 : rtio_sqe_prep_callback_no_cqe(complete_op, complete_op_cb, (void *)dev, iodev_sqe);
161 :
162 : rtio_submit(r, 0);
163 : }
164 :
165 : #ifdef __cplusplus
166 : }
167 : #endif
168 :
169 : #endif /* ZEPHYR_INCLUDE_RTIO_REGMAP_H_ */
|