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