1 /*
2 * Copyright (c) 2025-2026 Texas Instruments Incorporated - https://www.ti.com
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /*
8 * Device Core API
9 *
10 * This header defines the core device management API including device data
11 * structures, device lookup functions, driver callbacks, device group
12 * management, and device initialization/deinitialization operations.
13 */
14
15 #ifndef TI_DEVICE_H
16 #define TI_DEVICE_H
17
18 #include <cdefs.h>
19 #include <stddef.h>
20
21 #include <lib/utils_def.h>
22 #include <ti_container_of.h>
23 #include <ti_devgrps.h>
24 #include <ti_hosts.h>
25 #include <ti_pm_types.h>
26 #include <ti_psc_soc_device.h>
27
28 /* Invalid device ID marker */
29 #define TI_DEV_ID_NONE ((ti_dev_idx_t) (-1L))
30
31 /*
32 * Clock flags, shared with device flags field for devices with only one
33 * clock.
34 */
35 /* Disable device clock */
36 #define TI_DEV_CLK_FLAG_DISABLE BIT(0)
37
38 /* Host index for power-on enabled device state */
39 #define TI_DEV_POWER_ON_ENABLED_HOST_IDX TI_HOST_ID_CNT
40
41 /* Device flags */
42 /* Device retention mode flag */
43 #define TI_DEV_FLAG_RETENTION BIT(4)
44
45 /* Starting bit position for per-host enabled flags */
46 #define TI_DEV_FLAG_ENABLED_BIT 5UL
47
48 /* Generate per-host enabled flag for a given host index */
49 #define TI_DEV_FLAG_ENABLED(host_idx) (1ULL << ((TI_DEV_FLAG_ENABLED_BIT) + (host_idx)))
50
51 /* Device was enabled at power-on */
52 #define TI_DEV_FLAG_POWER_ON_ENABLED TI_DEV_FLAG_ENABLED(TI_DEV_POWER_ON_ENABLED_HOST_IDX)
53
54 /* Note, can support TI_HOST_ID_CNT up to 26 */
55 /* Mask covering all per-host enabled flags */
56 #define TI_DEV_FLAG_ENABLED_MASK (((1ULL << (TI_HOST_ID_CNT + 1ULL)) - 1ULL) << 5ULL)
57
58 /* Const flags for dev_data */
59
60 /* Set if struct ti_dev_data is contained within a drv_data */
61 #define TI_DEVD_FLAG_DRV_DATA BIT(0)
62
63 /*
64 * Set if the device is only for internal access and should not be accessible
65 * via the msgmgr API from the HLOS.
66 */
67 #define TI_DEVD_FLAG_INTERNAL BIT(1)
68
69 /* Set if the devices init callback should be called at boot */
70 #define TI_DEVD_FLAG_DO_INIT BIT(2)
71
72 /* Internal mapping from devices to device groups */
73 #define TI_PM_DEVGRP_00 1U
74
75 struct ti_device;
76 struct ti_dev_clk;
77 struct ti_dev_clk_data;
78
79 /*
80 * Device driver callback interface
81 *
82 * Provides lifecycle callbacks for device-specific initialization
83 * and deinitialization.
84 */
85 struct ti_drv {
86 /* Pre-initialization callback, returns error code on failure */
87 int32_t (*pre_init)(struct ti_device *dev);
88
89 /* Post-initialization callback, returns error code on failure */
90 int32_t (*post_init)(struct ti_device *dev);
91
92 /* Deinitialization callback */
93 void (*uninit)(struct ti_device *dev);
94 };
95
96 /*
97 * Constant device configuration data
98 *
99 * Contains immutable device properties including clock associations,
100 * SoC-specific data, and device group membership.
101 */
102 struct ti_dev_data {
103 /* Index into soc_dev_clk_data/soc_dev_clk array */
104 uint16_t dev_clk_idx;
105
106 /* SoC specific data */
107 struct ti_soc_device_data soc;
108
109 /* Number of device attached clocks */
110 uint16_t n_clocks;
111
112 /* Const flags for this device, DEVD_FLAG_... */
113 uint8_t flags;
114
115 /* Device group membership for power management */
116 uint8_t pm_devgrp;
117 };
118
119 /*
120 * Driver specific data for device
121 *
122 * This expands on the const device data to include data that is useful to
123 * a driver for the device. If a device is described by a drv_data struct,
124 * then the TI_DEVD_FLAG_DRV_DATA should be set.
125 */
126 struct ti_drv_data {
127 /* Driver for device if preset */
128 const struct ti_drv *drv;
129
130 /* Encapsulated dev_data */
131 struct ti_dev_data dev_data;
132 };
133
134 /*
135 * Dynamic device runtime data
136 *
137 * Tracks device state including ownership, initialization status, and
138 * runtime flags such as per-host enabled state and retention mode.
139 */
140 struct ti_device {
141 /* Runtime flags (DEV_FLAG_*) */
142 uint32_t flags;
143
144 /* Host index of exclusive owner+1, 0 for none */
145 uint8_t exclusive;
146
147 /* Initialization state flag */
148 uint8_t initialized;
149 };
150
151 /*
152 * Devgroup information
153 *
154 * Information to locate and describe devgroups. A device's dev_data will
155 * be located within it's devgroup elf section. The devgroup information
156 * describes the start and end of that section.
157 *
158 * The devgroup information also provides the dev_clk_data and dev_clk
159 * arrays for the devices within the devgroup. This allows these arrays
160 * to be stored within their respective devgroup section.
161 */
162 struct ti_devgroup {
163 /* dev_clk_data array for this devgroup */
164 const struct ti_dev_clk_data *dev_clk_data;
165
166 /* dev_clk array for this devgroup */
167 struct ti_dev_clk *dev_clk;
168
169 /* Starting clock index for this devgroup */
170 ti_clk_idx_t clk_idx;
171 };
172
173 /* Array of dynamic device runtime data for all SoC devices */
174 extern struct ti_device soc_devices[];
175
176 /* Total number of devices in the SoC */
177 extern const size_t soc_device_count;
178
179 /* Array of pointers to constant device configuration data */
180 extern const struct ti_dev_data *const soc_device_data_arr[];
181
182 /* Array of SoC device groups for power management */
183 extern const struct ti_devgroup soc_devgroups[];
184
185 /* Total number of device groups in the SoC */
186 extern const size_t soc_devgroup_count;
187
188 /**
189 * ti_pm_devgroup_is_enabled() - Test a set of devgroups for PM
190 * @groups: A bitfield of devgroups to test.
191 *
192 * Return: true if any of the devgroups in groups are enabled, false otherwise.
193 */
194 bool ti_pm_devgroup_is_enabled(devgrp_t groups);
195
196 int32_t ti_devices_init(void);
197
198 /**
199 * ti_devices_init_rw() - Complete deferred init.
200 *
201 * Ensure that deferred device init has completed. Note that if deferred init
202 * has already completed, this function takes no action and returns 0.
203 *
204 * Return: 0 on success, <0 otherwise.
205 */
206 int32_t ti_devices_init_rw(void);
207
208 /**
209 * ti_device_id_valid() - Determine if a device ID from the API is valid.
210 * @id: A 32 bit device ID from the msgmgr API.
211 *
212 * Return: True if the device ID refers to a valid SoC device, false otherwise
213 */
ti_device_id_valid(uint32_t id)214 static inline bool ti_device_id_valid(uint32_t id)
215 {
216 return (id < (uint32_t) soc_device_count) && (soc_device_data_arr[id] != NULL);
217 }
218
219 /*
220 * Internal lookup a device based on a device ID
221 *
222 * This does a lookup of a device based on the device ID and is meant only
223 * for internal use.
224 */
ti_device_lookup(ti_dev_idx_t id)225 static inline struct ti_device *ti_device_lookup(ti_dev_idx_t id)
226 {
227 return ti_device_id_valid(id) ? (soc_devices + id) : NULL;
228 }
229
230 /*
231 * API lookup a device based on a device ID
232 *
233 * This does a lookup of a device based on a API id from the msgmgr API.
234 * This function hides any devices with the TI_DEVD_FLAG_INTERNAL set.
235 */
ti_device_api_lookup(uint32_t id)236 static inline struct ti_device *ti_device_api_lookup(uint32_t id)
237 {
238 return (!ti_device_id_valid(id) ||
239 ((soc_device_data_arr[id]->flags & TI_DEVD_FLAG_INTERNAL) != 0U)) ?
240 NULL : (soc_devices + id);
241 }
242
243 /**
244 * ti_device_id() - Return the device ID based on a device pointer.
245 * @device: The device pointer.
246 *
247 * The device pointer is just an index into the array of devices. This is
248 * used to return a device ID. This function has no error checking for NULL
249 * pointers.
250 *
251 * Return: The device ID.
252 */
ti_device_id(struct ti_device * dev)253 static inline uint32_t ti_device_id(struct ti_device *dev)
254 {
255 return (uint32_t) (dev - soc_devices);
256 }
257
258 /*
259 * Return the dev_data struct associated with a device.
260 *
261 * The device pointer is translated to a device index based on it's position
262 * in the soc_devices array. That index is then used to find the correct
263 * element within the soc_device_data array.
264 */
ti_get_dev_data(struct ti_device * dev)265 static inline const struct ti_dev_data *ti_get_dev_data(struct ti_device *dev)
266 {
267 return soc_device_data_arr[ti_device_id(dev)];
268 }
269
270 /*
271 * Return a drv_data struct based on a passed dev_data struct
272 *
273 * The returned pointer is only valid if the TI_DEVD_FLAG_DRV_DATA flag is set.
274 */
ti_to_drv_data(const struct ti_dev_data * data)275 static inline const struct ti_drv_data *ti_to_drv_data(const struct ti_dev_data *data)
276 {
277 return ti_container_of(data, const struct ti_drv_data, dev_data);
278 }
279
280 /*
281 * Return the drv_data struct associated with a device.
282 *
283 * The returned pointer is only valid if the TI_DEVD_FLAG_DRV_DATA flag is set.
284 */
ti_get_drv_data(struct ti_device * dev)285 static inline const struct ti_drv_data *ti_get_drv_data(struct ti_device *dev)
286 {
287 const struct ti_dev_data *dev_datap = ti_get_dev_data(dev);
288
289 return dev_datap ? ti_to_drv_data(dev_datap) : NULL;
290 }
291
292 /*
293 * Find the devgroup associated with a given dev data entry.
294 *
295 * Each device is assigned to a devgroup. This function determines which
296 * devgroup a device is assigned to by checking where it's dev_data is
297 * stored.
298 */
ti_dev_data_lookup_devgroup(const struct ti_dev_data * data)299 static inline const struct ti_devgroup *ti_dev_data_lookup_devgroup(const struct ti_dev_data *data)
300 {
301 if (data == NULL) {
302 return NULL;
303 }
304
305 return &soc_devgroups[data->pm_devgrp];
306 }
307
308 #endif /* TI_DEVICE_H */
309