1 /*
2 * Copyright 2022 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #ifndef ZEPHYR_INCLUDE_DRIVERS_I3C_ADDRESSES_H_
8 #define ZEPHYR_INCLUDE_DRIVERS_I3C_ADDRESSES_H_
9
10 /**
11 * @brief I3C Address-related Helper Code
12 * @defgroup i3c_addresses I3C Address-related Helper Code
13 * @ingroup i3c_interface
14 * @{
15 */
16
17 #include <zephyr/types.h>
18 #include <zephyr/sys/sys_io.h>
19 #include <zephyr/sys/util.h>
20
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24
25 /** Broadcast Address on I3C bus. */
26 #define I3C_BROADCAST_ADDR 0x7E
27
28 /** Maximum value of device addresses. */
29 #define I3C_MAX_ADDR 0x7F
30
31 struct i3c_dev_list;
32
33 /**
34 * Enum to indicate whether an address is reserved, has I2C/I3C device attached,
35 * or no device attached.
36 */
37 enum i3c_addr_slot_status {
38 /** Address has not device attached. */
39 I3C_ADDR_SLOT_STATUS_FREE = 0U,
40
41 /** Address is reserved. */
42 I3C_ADDR_SLOT_STATUS_RSVD,
43
44 /** Address is associated with an I3C device. */
45 I3C_ADDR_SLOT_STATUS_I3C_DEV,
46
47 /** Address is associated with an I2C device. */
48 I3C_ADDR_SLOT_STATUS_I2C_DEV,
49
50 /** Bit masks used to filter status bits. */
51 I3C_ADDR_SLOT_STATUS_MASK = 0x03U,
52 };
53
54 /**
55 * @brief Structure to keep track of addresses on I3C bus.
56 */
57 struct i3c_addr_slots {
58 /* 2 bits per slot */
59 unsigned long slots[((I3C_MAX_ADDR + 1) * 2) / BITS_PER_LONG];
60 };
61
62 /**
63 * @brief Initialize the I3C address slots struct.
64 *
65 * This clears out the assigned address bits, and set the reserved
66 * address bits according to the I3C specification.
67 *
68 * @param dev Pointer to controller device driver instance.
69 *
70 * @retval 0 if successful.
71 * @retval -EINVAL if duplicate addresses.
72 */
73 int i3c_addr_slots_init(const struct device *dev);
74
75 /**
76 * @brief Set the address status of a device.
77 *
78 * @param slots Pointer to the address slots structure.
79 * @param dev_addr Device address.
80 * @param status New status for the address @p dev_addr.
81 */
82 void i3c_addr_slots_set(struct i3c_addr_slots *slots,
83 uint8_t dev_addr,
84 enum i3c_addr_slot_status status);
85
86 /**
87 * @brief Get the address status of a device.
88 *
89 * @param slots Pointer to the address slots structure.
90 * @param dev_addr Device address.
91 *
92 * @return Address status for the address @p dev_addr.
93 */
94 enum i3c_addr_slot_status i3c_addr_slots_status(struct i3c_addr_slots *slots,
95 uint8_t dev_addr);
96
97 /**
98 * @brief Check if the address is free.
99 *
100 * @param slots Pointer to the address slots structure.
101 * @param dev_addr Device address.
102 *
103 * @retval true if address is free.
104 * @retval false if address is not free.
105 */
106 bool i3c_addr_slots_is_free(struct i3c_addr_slots *slots,
107 uint8_t dev_addr);
108
109 /**
110 * @brief Find the next free address.
111 *
112 * This can be used to find the next free address that can be
113 * assigned to a new device.
114 *
115 * @param slots Pointer to the address slots structure.
116 * @param start_addr Where to start searching
117 *
118 * @return The next free address, or 0 if none found.
119 */
120 uint8_t i3c_addr_slots_next_free_find(struct i3c_addr_slots *slots, uint8_t start_addr);
121
122 /**
123 * @brief Mark the address as free (not used) in device list.
124 *
125 * @param addr_slots Pointer to the address slots struct.
126 * @param addr Device address.
127 */
i3c_addr_slots_mark_free(struct i3c_addr_slots * addr_slots,uint8_t addr)128 static inline void i3c_addr_slots_mark_free(struct i3c_addr_slots *addr_slots,
129 uint8_t addr)
130 {
131 i3c_addr_slots_set(addr_slots, addr,
132 I3C_ADDR_SLOT_STATUS_FREE);
133 }
134
135 /**
136 * @brief Mark the address as reserved in device list.
137 *
138 * @param addr_slots Pointer to the address slots struct.
139 * @param addr Device address.
140 */
i3c_addr_slots_mark_rsvd(struct i3c_addr_slots * addr_slots,uint8_t addr)141 static inline void i3c_addr_slots_mark_rsvd(struct i3c_addr_slots *addr_slots,
142 uint8_t addr)
143 {
144 i3c_addr_slots_set(addr_slots, addr,
145 I3C_ADDR_SLOT_STATUS_RSVD);
146 }
147
148 /**
149 * @brief Mark the address as I3C device in device list.
150 *
151 * @param addr_slots Pointer to the address slots struct.
152 * @param addr Device address.
153 */
i3c_addr_slots_mark_i3c(struct i3c_addr_slots * addr_slots,uint8_t addr)154 static inline void i3c_addr_slots_mark_i3c(struct i3c_addr_slots *addr_slots,
155 uint8_t addr)
156 {
157 i3c_addr_slots_set(addr_slots, addr,
158 I3C_ADDR_SLOT_STATUS_I3C_DEV);
159 }
160
161 /**
162 * @brief Mark the address as I2C device in device list.
163 *
164 * @param addr_slots Pointer to the address slots struct.
165 * @param addr Device address.
166 */
i3c_addr_slots_mark_i2c(struct i3c_addr_slots * addr_slots,uint8_t addr)167 static inline void i3c_addr_slots_mark_i2c(struct i3c_addr_slots *addr_slots,
168 uint8_t addr)
169 {
170 i3c_addr_slots_set(addr_slots, addr,
171 I3C_ADDR_SLOT_STATUS_I2C_DEV);
172 }
173
174 #ifdef __cplusplus
175 }
176 #endif
177
178 /**
179 * @}
180 */
181
182 #endif /* ZEPHYR_INCLUDE_DRIVERS_I3C_ADDRESSES_H_ */
183