/* * Copyright (c) 2025-2026 Texas Instruments Incorporated - https://www.ti.com * * SPDX-License-Identifier: BSD-3-Clause */ /* * Device Initialization and Management * * This module provides core device initialization, deferred initialization * support, and device lifecycle management for the device power management subsystem. */ #include #include #include #include #include #include #include #include /* True if deferred (read-write) initialization has been initiated. */ static bool devices_rw; bool ti_pm_devgroup_is_enabled(devgrp_t groups) { return true; } /** * device_init() - Initialize a device * @dev: The device to init. * * This performs the necessary device initialization step, including syncing * the flags on the device with the real hardware state and calling the clock * init function for each clock. * * Return: 0 on success, <0 on failure. */ static int32_t device_init(struct ti_device *dev) { const struct ti_dev_data *data; const struct ti_drv *drvp = NULL; uint16_t i; int32_t ret; assert(dev != NULL); data = ti_get_dev_data(dev); if (data == NULL) { return 0; } if (((data->flags & TI_DEVD_FLAG_DRV_DATA) != 0U) && ((data->flags & TI_DEVD_FLAG_DO_INIT) != 0U)) { drvp = ti_to_drv_data(data)->drv; } if ((drvp != NULL) && (drvp->pre_init != NULL)) { ret = drvp->pre_init(dev); if (ret != 0) { return ret; } } if (devices_rw == false) { /* Defer remainder of init */ return 0; } ret = ti_soc_device_init(dev); if (ret != 0) { return ret; } for (i = 0U; i < data->n_clocks; i++) { ti_device_clk_init(dev, i); } /* Calling these multiple times for a deferred device has no effect */ if (ti_device_get_state(dev) != 0U) { ti_device_set_state(dev, TI_DEV_POWER_ON_ENABLED_HOST_IDX, true); ti_device_set_retention(dev, true); } if ((drvp != NULL) && (drvp->post_init != NULL)) { ret = drvp->post_init(dev); if (ret != 0) { return ret; } } return 0; } int32_t ti_devices_init(void) { bool done; bool progress; bool contents; ti_dev_idx_t idx; contents = false; do { struct ti_device *dev; done = true; progress = false; for (idx = 0U; idx < soc_device_count; idx++) { devgrp_t devgrp; int32_t ret; dev = &soc_devices[idx]; if (dev->initialized != 0U) { continue; } if (soc_device_data_arr[idx] == NULL) { continue; } /* Translate compressed internal representation to bitfield */ devgrp = (devgrp_t) BIT(soc_device_data_arr[idx]->pm_devgrp - 1U); if (ti_pm_devgroup_is_enabled(devgrp) == false) { continue; } contents = true; ret = device_init(dev); if (ret == -EAGAIN) { done = false; continue; } if (ret < 0) { VERBOSE("ACTION FAIL: DEV_INIT dev_id=%d error=%d\n", idx, -ret); } progress = true; dev->initialized = 1U; } } while (!done && progress); if (devices_rw == true) { /* Only necessary after deferred initialization */ ti_clk_drop_pwr_up_en(); } if ((progress == false) && (contents == true)) { /* We processed at least one device but didn't make progress */ return -EAGAIN; } return 0; } int32_t ti_devices_init_rw(void) { if (devices_rw == false) { uint32_t i; /* * Force reinitialization of all devices to get deferred * initialization. */ for (i = 0U; i < soc_device_count; i++) { struct ti_device *dev = &soc_devices[i]; dev->initialized = 0U; } devices_rw = true; /* Perform deferred initialization */ return ti_devices_init(); } return 0; }