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