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