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