1*43b5c095SKamlesh Gurudasani /*
2*43b5c095SKamlesh Gurudasani * Copyright (c) 2025-2026 Texas Instruments Incorporated - https://www.ti.com
3*43b5c095SKamlesh Gurudasani *
4*43b5c095SKamlesh Gurudasani * SPDX-License-Identifier: BSD-3-Clause
5*43b5c095SKamlesh Gurudasani */
6*43b5c095SKamlesh Gurudasani
7*43b5c095SKamlesh Gurudasani /*
8*43b5c095SKamlesh Gurudasani * Device Initialization and Management
9*43b5c095SKamlesh Gurudasani *
10*43b5c095SKamlesh Gurudasani * This module provides core device initialization, deferred initialization
11*43b5c095SKamlesh Gurudasani * support, and device lifecycle management for the device power management subsystem.
12*43b5c095SKamlesh Gurudasani */
13*43b5c095SKamlesh Gurudasani
14*43b5c095SKamlesh Gurudasani #include <assert.h>
15*43b5c095SKamlesh Gurudasani #include <errno.h>
16*43b5c095SKamlesh Gurudasani #include <stddef.h>
17*43b5c095SKamlesh Gurudasani
18*43b5c095SKamlesh Gurudasani #include <common/debug.h>
19*43b5c095SKamlesh Gurudasani #include <ti_clk.h>
20*43b5c095SKamlesh Gurudasani #include <ti_device.h>
21*43b5c095SKamlesh Gurudasani #include <ti_device_clk.h>
22*43b5c095SKamlesh Gurudasani #include <ti_device_pm.h>
23*43b5c095SKamlesh Gurudasani
24*43b5c095SKamlesh Gurudasani /* True if deferred (read-write) initialization has been initiated. */
25*43b5c095SKamlesh Gurudasani static bool devices_rw;
26*43b5c095SKamlesh Gurudasani
ti_pm_devgroup_is_enabled(devgrp_t groups)27*43b5c095SKamlesh Gurudasani bool ti_pm_devgroup_is_enabled(devgrp_t groups)
28*43b5c095SKamlesh Gurudasani {
29*43b5c095SKamlesh Gurudasani return true;
30*43b5c095SKamlesh Gurudasani }
31*43b5c095SKamlesh Gurudasani
32*43b5c095SKamlesh Gurudasani /**
33*43b5c095SKamlesh Gurudasani * device_init() - Initialize a device
34*43b5c095SKamlesh Gurudasani * @dev: The device to init.
35*43b5c095SKamlesh Gurudasani *
36*43b5c095SKamlesh Gurudasani * This performs the necessary device initialization step, including syncing
37*43b5c095SKamlesh Gurudasani * the flags on the device with the real hardware state and calling the clock
38*43b5c095SKamlesh Gurudasani * init function for each clock.
39*43b5c095SKamlesh Gurudasani *
40*43b5c095SKamlesh Gurudasani * Return: 0 on success, <0 on failure.
41*43b5c095SKamlesh Gurudasani */
device_init(struct ti_device * dev)42*43b5c095SKamlesh Gurudasani static int32_t device_init(struct ti_device *dev)
43*43b5c095SKamlesh Gurudasani {
44*43b5c095SKamlesh Gurudasani const struct ti_dev_data *data;
45*43b5c095SKamlesh Gurudasani const struct ti_drv *drvp = NULL;
46*43b5c095SKamlesh Gurudasani uint16_t i;
47*43b5c095SKamlesh Gurudasani int32_t ret;
48*43b5c095SKamlesh Gurudasani
49*43b5c095SKamlesh Gurudasani assert(dev != NULL);
50*43b5c095SKamlesh Gurudasani
51*43b5c095SKamlesh Gurudasani data = ti_get_dev_data(dev);
52*43b5c095SKamlesh Gurudasani if (data == NULL) {
53*43b5c095SKamlesh Gurudasani return 0;
54*43b5c095SKamlesh Gurudasani }
55*43b5c095SKamlesh Gurudasani
56*43b5c095SKamlesh Gurudasani if (((data->flags & TI_DEVD_FLAG_DRV_DATA) != 0U) &&
57*43b5c095SKamlesh Gurudasani ((data->flags & TI_DEVD_FLAG_DO_INIT) != 0U)) {
58*43b5c095SKamlesh Gurudasani drvp = ti_to_drv_data(data)->drv;
59*43b5c095SKamlesh Gurudasani }
60*43b5c095SKamlesh Gurudasani
61*43b5c095SKamlesh Gurudasani if ((drvp != NULL) && (drvp->pre_init != NULL)) {
62*43b5c095SKamlesh Gurudasani ret = drvp->pre_init(dev);
63*43b5c095SKamlesh Gurudasani if (ret != 0) {
64*43b5c095SKamlesh Gurudasani return ret;
65*43b5c095SKamlesh Gurudasani }
66*43b5c095SKamlesh Gurudasani }
67*43b5c095SKamlesh Gurudasani
68*43b5c095SKamlesh Gurudasani if (devices_rw == false) {
69*43b5c095SKamlesh Gurudasani /* Defer remainder of init */
70*43b5c095SKamlesh Gurudasani return 0;
71*43b5c095SKamlesh Gurudasani }
72*43b5c095SKamlesh Gurudasani
73*43b5c095SKamlesh Gurudasani ret = ti_soc_device_init(dev);
74*43b5c095SKamlesh Gurudasani if (ret != 0) {
75*43b5c095SKamlesh Gurudasani return ret;
76*43b5c095SKamlesh Gurudasani }
77*43b5c095SKamlesh Gurudasani
78*43b5c095SKamlesh Gurudasani for (i = 0U; i < data->n_clocks; i++) {
79*43b5c095SKamlesh Gurudasani ti_device_clk_init(dev, i);
80*43b5c095SKamlesh Gurudasani }
81*43b5c095SKamlesh Gurudasani
82*43b5c095SKamlesh Gurudasani /* Calling these multiple times for a deferred device has no effect */
83*43b5c095SKamlesh Gurudasani if (ti_device_get_state(dev) != 0U) {
84*43b5c095SKamlesh Gurudasani ti_device_set_state(dev, TI_DEV_POWER_ON_ENABLED_HOST_IDX, true);
85*43b5c095SKamlesh Gurudasani ti_device_set_retention(dev, true);
86*43b5c095SKamlesh Gurudasani }
87*43b5c095SKamlesh Gurudasani
88*43b5c095SKamlesh Gurudasani if ((drvp != NULL) && (drvp->post_init != NULL)) {
89*43b5c095SKamlesh Gurudasani ret = drvp->post_init(dev);
90*43b5c095SKamlesh Gurudasani if (ret != 0) {
91*43b5c095SKamlesh Gurudasani return ret;
92*43b5c095SKamlesh Gurudasani }
93*43b5c095SKamlesh Gurudasani }
94*43b5c095SKamlesh Gurudasani
95*43b5c095SKamlesh Gurudasani return 0;
96*43b5c095SKamlesh Gurudasani }
97*43b5c095SKamlesh Gurudasani
ti_devices_init(void)98*43b5c095SKamlesh Gurudasani int32_t ti_devices_init(void)
99*43b5c095SKamlesh Gurudasani {
100*43b5c095SKamlesh Gurudasani bool done;
101*43b5c095SKamlesh Gurudasani bool progress;
102*43b5c095SKamlesh Gurudasani bool contents;
103*43b5c095SKamlesh Gurudasani ti_dev_idx_t idx;
104*43b5c095SKamlesh Gurudasani
105*43b5c095SKamlesh Gurudasani contents = false;
106*43b5c095SKamlesh Gurudasani do {
107*43b5c095SKamlesh Gurudasani struct ti_device *dev;
108*43b5c095SKamlesh Gurudasani
109*43b5c095SKamlesh Gurudasani done = true;
110*43b5c095SKamlesh Gurudasani progress = false;
111*43b5c095SKamlesh Gurudasani
112*43b5c095SKamlesh Gurudasani for (idx = 0U; idx < soc_device_count; idx++) {
113*43b5c095SKamlesh Gurudasani devgrp_t devgrp;
114*43b5c095SKamlesh Gurudasani int32_t ret;
115*43b5c095SKamlesh Gurudasani
116*43b5c095SKamlesh Gurudasani dev = &soc_devices[idx];
117*43b5c095SKamlesh Gurudasani if (dev->initialized != 0U) {
118*43b5c095SKamlesh Gurudasani continue;
119*43b5c095SKamlesh Gurudasani }
120*43b5c095SKamlesh Gurudasani
121*43b5c095SKamlesh Gurudasani if (soc_device_data_arr[idx] == NULL) {
122*43b5c095SKamlesh Gurudasani continue;
123*43b5c095SKamlesh Gurudasani }
124*43b5c095SKamlesh Gurudasani
125*43b5c095SKamlesh Gurudasani /* Translate compressed internal representation to bitfield */
126*43b5c095SKamlesh Gurudasani devgrp = (devgrp_t) BIT(soc_device_data_arr[idx]->pm_devgrp - 1U);
127*43b5c095SKamlesh Gurudasani
128*43b5c095SKamlesh Gurudasani if (ti_pm_devgroup_is_enabled(devgrp) == false) {
129*43b5c095SKamlesh Gurudasani continue;
130*43b5c095SKamlesh Gurudasani }
131*43b5c095SKamlesh Gurudasani
132*43b5c095SKamlesh Gurudasani contents = true;
133*43b5c095SKamlesh Gurudasani
134*43b5c095SKamlesh Gurudasani ret = device_init(dev);
135*43b5c095SKamlesh Gurudasani if (ret == -EAGAIN) {
136*43b5c095SKamlesh Gurudasani done = false;
137*43b5c095SKamlesh Gurudasani continue;
138*43b5c095SKamlesh Gurudasani }
139*43b5c095SKamlesh Gurudasani
140*43b5c095SKamlesh Gurudasani if (ret < 0) {
141*43b5c095SKamlesh Gurudasani VERBOSE("ACTION FAIL: DEV_INIT dev_id=%d error=%d\n",
142*43b5c095SKamlesh Gurudasani idx, -ret);
143*43b5c095SKamlesh Gurudasani }
144*43b5c095SKamlesh Gurudasani
145*43b5c095SKamlesh Gurudasani progress = true;
146*43b5c095SKamlesh Gurudasani dev->initialized = 1U;
147*43b5c095SKamlesh Gurudasani }
148*43b5c095SKamlesh Gurudasani } while (!done && progress);
149*43b5c095SKamlesh Gurudasani
150*43b5c095SKamlesh Gurudasani if (devices_rw == true) {
151*43b5c095SKamlesh Gurudasani /* Only necessary after deferred initialization */
152*43b5c095SKamlesh Gurudasani ti_clk_drop_pwr_up_en();
153*43b5c095SKamlesh Gurudasani }
154*43b5c095SKamlesh Gurudasani
155*43b5c095SKamlesh Gurudasani if ((progress == false) && (contents == true)) {
156*43b5c095SKamlesh Gurudasani /* We processed at least one device but didn't make progress */
157*43b5c095SKamlesh Gurudasani return -EAGAIN;
158*43b5c095SKamlesh Gurudasani }
159*43b5c095SKamlesh Gurudasani
160*43b5c095SKamlesh Gurudasani return 0;
161*43b5c095SKamlesh Gurudasani }
162*43b5c095SKamlesh Gurudasani
ti_devices_init_rw(void)163*43b5c095SKamlesh Gurudasani int32_t ti_devices_init_rw(void)
164*43b5c095SKamlesh Gurudasani {
165*43b5c095SKamlesh Gurudasani if (devices_rw == false) {
166*43b5c095SKamlesh Gurudasani uint32_t i;
167*43b5c095SKamlesh Gurudasani
168*43b5c095SKamlesh Gurudasani /*
169*43b5c095SKamlesh Gurudasani * Force reinitialization of all devices to get deferred
170*43b5c095SKamlesh Gurudasani * initialization.
171*43b5c095SKamlesh Gurudasani */
172*43b5c095SKamlesh Gurudasani for (i = 0U; i < soc_device_count; i++) {
173*43b5c095SKamlesh Gurudasani struct ti_device *dev = &soc_devices[i];
174*43b5c095SKamlesh Gurudasani
175*43b5c095SKamlesh Gurudasani dev->initialized = 0U;
176*43b5c095SKamlesh Gurudasani }
177*43b5c095SKamlesh Gurudasani
178*43b5c095SKamlesh Gurudasani devices_rw = true;
179*43b5c095SKamlesh Gurudasani
180*43b5c095SKamlesh Gurudasani /* Perform deferred initialization */
181*43b5c095SKamlesh Gurudasani return ti_devices_init();
182*43b5c095SKamlesh Gurudasani }
183*43b5c095SKamlesh Gurudasani
184*43b5c095SKamlesh Gurudasani return 0;
185*43b5c095SKamlesh Gurudasani }
186