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