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 *
117 * @return The next free address, or 0 if none found.
118 */
119 uint8_t i3c_addr_slots_next_free_find(struct i3c_addr_slots *slots);
120
121 /**
122 * @brief Mark the address as free (not used) in device list.
123 *
124 * @param addr_slots Pointer to the address slots struct.
125 * @param addr Device address.
126 */
i3c_addr_slots_mark_free(struct i3c_addr_slots * addr_slots,uint8_t addr)127 static inline void i3c_addr_slots_mark_free(struct i3c_addr_slots *addr_slots,
128 uint8_t addr)
129 {
130 i3c_addr_slots_set(addr_slots, addr,
131 I3C_ADDR_SLOT_STATUS_FREE);
132 }
133
134 /**
135 * @brief Mark the address as reserved in device list.
136 *
137 * @param addr_slots Pointer to the address slots struct.
138 * @param addr Device address.
139 */
i3c_addr_slots_mark_rsvd(struct i3c_addr_slots * addr_slots,uint8_t addr)140 static inline void i3c_addr_slots_mark_rsvd(struct i3c_addr_slots *addr_slots,
141 uint8_t addr)
142 {
143 i3c_addr_slots_set(addr_slots, addr,
144 I3C_ADDR_SLOT_STATUS_RSVD);
145 }
146
147 /**
148 * @brief Mark the address as I3C device in device list.
149 *
150 * @param addr_slots Pointer to the address slots struct.
151 * @param addr Device address.
152 */
i3c_addr_slots_mark_i3c(struct i3c_addr_slots * addr_slots,uint8_t addr)153 static inline void i3c_addr_slots_mark_i3c(struct i3c_addr_slots *addr_slots,
154 uint8_t addr)
155 {
156 i3c_addr_slots_set(addr_slots, addr,
157 I3C_ADDR_SLOT_STATUS_I3C_DEV);
158 }
159
160 /**
161 * @brief Mark the address as I2C device in device list.
162 *
163 * @param addr_slots Pointer to the address slots struct.
164 * @param addr Device address.
165 */
i3c_addr_slots_mark_i2c(struct i3c_addr_slots * addr_slots,uint8_t addr)166 static inline void i3c_addr_slots_mark_i2c(struct i3c_addr_slots *addr_slots,
167 uint8_t addr)
168 {
169 i3c_addr_slots_set(addr_slots, addr,
170 I3C_ADDR_SLOT_STATUS_I2C_DEV);
171 }
172
173 #ifdef __cplusplus
174 }
175 #endif
176
177 /**
178 * @}
179 */
180
181 #endif /* ZEPHYR_INCLUDE_DRIVERS_I3C_ADDRESSES_H_ */
182