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