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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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