xref: /rk3399_ARM-atf/drivers/ti/pd/include/ti_device.h (revision a28114d66a6d43db4accef5fd5d6dab6c059e584)
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