/* * Copyright (c) 2025-2026 Texas Instruments Incorporated - https://www.ti.com * * SPDX-License-Identifier: BSD-3-Clause */ /* * Device Core API * * This header defines the core device management API including device data * structures, device lookup functions, driver callbacks, device group * management, and device initialization/deinitialization operations. */ #ifndef TI_DEVICE_H #define TI_DEVICE_H #include #include #include #include #include #include #include #include /* Invalid device ID marker */ #define TI_DEV_ID_NONE ((ti_dev_idx_t) (-1L)) /* * Clock flags, shared with device flags field for devices with only one * clock. */ /* Disable device clock */ #define TI_DEV_CLK_FLAG_DISABLE BIT(0) /* Host index for power-on enabled device state */ #define TI_DEV_POWER_ON_ENABLED_HOST_IDX TI_HOST_ID_CNT /* Device flags */ /* Device retention mode flag */ #define TI_DEV_FLAG_RETENTION BIT(4) /* Starting bit position for per-host enabled flags */ #define TI_DEV_FLAG_ENABLED_BIT 5UL /* Generate per-host enabled flag for a given host index */ #define TI_DEV_FLAG_ENABLED(host_idx) (1ULL << ((TI_DEV_FLAG_ENABLED_BIT) + (host_idx))) /* Device was enabled at power-on */ #define TI_DEV_FLAG_POWER_ON_ENABLED TI_DEV_FLAG_ENABLED(TI_DEV_POWER_ON_ENABLED_HOST_IDX) /* Note, can support TI_HOST_ID_CNT up to 26 */ /* Mask covering all per-host enabled flags */ #define TI_DEV_FLAG_ENABLED_MASK (((1ULL << (TI_HOST_ID_CNT + 1ULL)) - 1ULL) << 5ULL) /* Const flags for dev_data */ /* Set if struct ti_dev_data is contained within a drv_data */ #define TI_DEVD_FLAG_DRV_DATA BIT(0) /* * Set if the device is only for internal access and should not be accessible * via the msgmgr API from the HLOS. */ #define TI_DEVD_FLAG_INTERNAL BIT(1) /* Set if the devices init callback should be called at boot */ #define TI_DEVD_FLAG_DO_INIT BIT(2) /* Internal mapping from devices to device groups */ #define TI_PM_DEVGRP_00 1U struct ti_device; struct ti_dev_clk; struct ti_dev_clk_data; /* * Device driver callback interface * * Provides lifecycle callbacks for device-specific initialization * and deinitialization. */ struct ti_drv { /* Pre-initialization callback, returns error code on failure */ int32_t (*pre_init)(struct ti_device *dev); /* Post-initialization callback, returns error code on failure */ int32_t (*post_init)(struct ti_device *dev); /* Deinitialization callback */ void (*uninit)(struct ti_device *dev); }; /* * Constant device configuration data * * Contains immutable device properties including clock associations, * SoC-specific data, and device group membership. */ struct ti_dev_data { /* Index into soc_dev_clk_data/soc_dev_clk array */ uint16_t dev_clk_idx; /* SoC specific data */ struct ti_soc_device_data soc; /* Number of device attached clocks */ uint16_t n_clocks; /* Const flags for this device, DEVD_FLAG_... */ uint8_t flags; /* Device group membership for power management */ uint8_t pm_devgrp; }; /* * Driver specific data for device * * This expands on the const device data to include data that is useful to * a driver for the device. If a device is described by a drv_data struct, * then the TI_DEVD_FLAG_DRV_DATA should be set. */ struct ti_drv_data { /* Driver for device if preset */ const struct ti_drv *drv; /* Encapsulated dev_data */ struct ti_dev_data dev_data; }; /* * Dynamic device runtime data * * Tracks device state including ownership, initialization status, and * runtime flags such as per-host enabled state and retention mode. */ struct ti_device { /* Runtime flags (DEV_FLAG_*) */ uint32_t flags; /* Host index of exclusive owner+1, 0 for none */ uint8_t exclusive; /* Initialization state flag */ uint8_t initialized; }; /* * Devgroup information * * Information to locate and describe devgroups. A device's dev_data will * be located within it's devgroup elf section. The devgroup information * describes the start and end of that section. * * The devgroup information also provides the dev_clk_data and dev_clk * arrays for the devices within the devgroup. This allows these arrays * to be stored within their respective devgroup section. */ struct ti_devgroup { /* dev_clk_data array for this devgroup */ const struct ti_dev_clk_data *dev_clk_data; /* dev_clk array for this devgroup */ struct ti_dev_clk *dev_clk; /* Starting clock index for this devgroup */ ti_clk_idx_t clk_idx; }; /* Array of dynamic device runtime data for all SoC devices */ extern struct ti_device soc_devices[]; /* Total number of devices in the SoC */ extern const size_t soc_device_count; /* Array of pointers to constant device configuration data */ extern const struct ti_dev_data *const soc_device_data_arr[]; /* Array of SoC device groups for power management */ extern const struct ti_devgroup soc_devgroups[]; /* Total number of device groups in the SoC */ extern const size_t soc_devgroup_count; /** * ti_pm_devgroup_is_enabled() - Test a set of devgroups for PM * @groups: A bitfield of devgroups to test. * * Return: true if any of the devgroups in groups are enabled, false otherwise. */ bool ti_pm_devgroup_is_enabled(devgrp_t groups); int32_t ti_devices_init(void); /** * ti_devices_init_rw() - Complete deferred init. * * Ensure that deferred device init has completed. Note that if deferred init * has already completed, this function takes no action and returns 0. * * Return: 0 on success, <0 otherwise. */ int32_t ti_devices_init_rw(void); /** * ti_device_id_valid() - Determine if a device ID from the API is valid. * @id: A 32 bit device ID from the msgmgr API. * * Return: True if the device ID refers to a valid SoC device, false otherwise */ static inline bool ti_device_id_valid(uint32_t id) { return (id < (uint32_t) soc_device_count) && (soc_device_data_arr[id] != NULL); } /* * Internal lookup a device based on a device ID * * This does a lookup of a device based on the device ID and is meant only * for internal use. */ static inline struct ti_device *ti_device_lookup(ti_dev_idx_t id) { return ti_device_id_valid(id) ? (soc_devices + id) : NULL; } /* * API lookup a device based on a device ID * * This does a lookup of a device based on a API id from the msgmgr API. * This function hides any devices with the TI_DEVD_FLAG_INTERNAL set. */ static inline struct ti_device *ti_device_api_lookup(uint32_t id) { return (!ti_device_id_valid(id) || ((soc_device_data_arr[id]->flags & TI_DEVD_FLAG_INTERNAL) != 0U)) ? NULL : (soc_devices + id); } /** * ti_device_id() - Return the device ID based on a device pointer. * @device: The device pointer. * * The device pointer is just an index into the array of devices. This is * used to return a device ID. This function has no error checking for NULL * pointers. * * Return: The device ID. */ static inline uint32_t ti_device_id(struct ti_device *dev) { return (uint32_t) (dev - soc_devices); } /* * Return the dev_data struct associated with a device. * * The device pointer is translated to a device index based on it's position * in the soc_devices array. That index is then used to find the correct * element within the soc_device_data array. */ static inline const struct ti_dev_data *ti_get_dev_data(struct ti_device *dev) { return soc_device_data_arr[ti_device_id(dev)]; } /* * Return a drv_data struct based on a passed dev_data struct * * The returned pointer is only valid if the TI_DEVD_FLAG_DRV_DATA flag is set. */ static inline const struct ti_drv_data *ti_to_drv_data(const struct ti_dev_data *data) { return ti_container_of(data, const struct ti_drv_data, dev_data); } /* * Return the drv_data struct associated with a device. * * The returned pointer is only valid if the TI_DEVD_FLAG_DRV_DATA flag is set. */ static inline const struct ti_drv_data *ti_get_drv_data(struct ti_device *dev) { const struct ti_dev_data *dev_datap = ti_get_dev_data(dev); return dev_datap ? ti_to_drv_data(dev_datap) : NULL; } /* * Find the devgroup associated with a given dev data entry. * * Each device is assigned to a devgroup. This function determines which * devgroup a device is assigned to by checking where it's dev_data is * stored. */ static inline const struct ti_devgroup *ti_dev_data_lookup_devgroup(const struct ti_dev_data *data) { if (data == NULL) { return NULL; } return &soc_devgroups[data->pm_devgrp]; } #endif /* TI_DEVICE_H */