1*92ee37ffSKamlesh Gurudasani /*
2*92ee37ffSKamlesh Gurudasani * Copyright (c) 2025-2026 Texas Instruments Incorporated - https://www.ti.com
3*92ee37ffSKamlesh Gurudasani *
4*92ee37ffSKamlesh Gurudasani * SPDX-License-Identifier: BSD-3-Clause
5*92ee37ffSKamlesh Gurudasani */
6*92ee37ffSKamlesh Gurudasani
7*92ee37ffSKamlesh Gurudasani /*
8*92ee37ffSKamlesh Gurudasani * Device Power Management
9*92ee37ffSKamlesh Gurudasani *
10*92ee37ffSKamlesh Gurudasani * This module handles the main device power management operations including
11*92ee37ffSKamlesh Gurudasani * device enable/disable, state management, retention control, and suspend handling.
12*92ee37ffSKamlesh Gurudasani */
13*92ee37ffSKamlesh Gurudasani
14*92ee37ffSKamlesh Gurudasani #include <assert.h>
15*92ee37ffSKamlesh Gurudasani
16*92ee37ffSKamlesh Gurudasani #include <ti_device.h>
17*92ee37ffSKamlesh Gurudasani #include <ti_device_clk.h>
18*92ee37ffSKamlesh Gurudasani #include <ti_device_pm.h>
19*92ee37ffSKamlesh Gurudasani
20*92ee37ffSKamlesh Gurudasani /**
21*92ee37ffSKamlesh Gurudasani * device_enable() - Enable a device.
22*92ee37ffSKamlesh Gurudasani * @dev: The device to enable.
23*92ee37ffSKamlesh Gurudasani *
24*92ee37ffSKamlesh Gurudasani * Performs the steps necessary to enable a device.
25*92ee37ffSKamlesh Gurudasani */
device_enable(struct ti_device * dev)26*92ee37ffSKamlesh Gurudasani static void device_enable(struct ti_device *dev)
27*92ee37ffSKamlesh Gurudasani {
28*92ee37ffSKamlesh Gurudasani const struct ti_dev_data *data;
29*92ee37ffSKamlesh Gurudasani uint16_t i;
30*92ee37ffSKamlesh Gurudasani
31*92ee37ffSKamlesh Gurudasani assert(dev != NULL);
32*92ee37ffSKamlesh Gurudasani
33*92ee37ffSKamlesh Gurudasani data = ti_get_dev_data(dev);
34*92ee37ffSKamlesh Gurudasani
35*92ee37ffSKamlesh Gurudasani for (i = 0U; i < data->n_clocks; i++) {
36*92ee37ffSKamlesh Gurudasani ti_device_clk_enable(dev, i);
37*92ee37ffSKamlesh Gurudasani }
38*92ee37ffSKamlesh Gurudasani ti_soc_device_enable(dev);
39*92ee37ffSKamlesh Gurudasani }
40*92ee37ffSKamlesh Gurudasani
41*92ee37ffSKamlesh Gurudasani /**
42*92ee37ffSKamlesh Gurudasani * ti_device_disable() - Disables a device.
43*92ee37ffSKamlesh Gurudasani * @device: The device to modify.
44*92ee37ffSKamlesh Gurudasani * @domain_reset: True if the device is being disabled due to a domain reset.
45*92ee37ffSKamlesh Gurudasani *
46*92ee37ffSKamlesh Gurudasani * Performs the steps necessary to disable a device.
47*92ee37ffSKamlesh Gurudasani */
ti_device_disable(struct ti_device * dev,bool domain_reset)48*92ee37ffSKamlesh Gurudasani void ti_device_disable(struct ti_device *dev, bool domain_reset)
49*92ee37ffSKamlesh Gurudasani {
50*92ee37ffSKamlesh Gurudasani const struct ti_dev_data *data;
51*92ee37ffSKamlesh Gurudasani int32_t i;
52*92ee37ffSKamlesh Gurudasani
53*92ee37ffSKamlesh Gurudasani assert(dev != NULL);
54*92ee37ffSKamlesh Gurudasani
55*92ee37ffSKamlesh Gurudasani data = ti_get_dev_data(dev);
56*92ee37ffSKamlesh Gurudasani
57*92ee37ffSKamlesh Gurudasani ti_soc_device_disable(dev, domain_reset);
58*92ee37ffSKamlesh Gurudasani
59*92ee37ffSKamlesh Gurudasani for (i = (int32_t) data->n_clocks - 1; i >= 0; i--) {
60*92ee37ffSKamlesh Gurudasani ti_device_clk_disable(dev, (uint16_t) i);
61*92ee37ffSKamlesh Gurudasani }
62*92ee37ffSKamlesh Gurudasani }
63*92ee37ffSKamlesh Gurudasani
64*92ee37ffSKamlesh Gurudasani /**
65*92ee37ffSKamlesh Gurudasani * ti_device_clear_flags() - Clear device initialization flags.
66*92ee37ffSKamlesh Gurudasani * @dev: The device to modify.
67*92ee37ffSKamlesh Gurudasani */
ti_device_clear_flags(struct ti_device * dev)68*92ee37ffSKamlesh Gurudasani void ti_device_clear_flags(struct ti_device *dev)
69*92ee37ffSKamlesh Gurudasani {
70*92ee37ffSKamlesh Gurudasani assert(dev != NULL);
71*92ee37ffSKamlesh Gurudasani
72*92ee37ffSKamlesh Gurudasani ti_soc_device_clear_flags(dev);
73*92ee37ffSKamlesh Gurudasani }
74*92ee37ffSKamlesh Gurudasani
75*92ee37ffSKamlesh Gurudasani /**
76*92ee37ffSKamlesh Gurudasani * ti_device_set_state() - Set device enabled state.
77*92ee37ffSKamlesh Gurudasani * @device_ptr: The device to modify.
78*92ee37ffSKamlesh Gurudasani * @host_idx: Index of the host making the request.
79*92ee37ffSKamlesh Gurudasani * @enable: True to enable the device, false to disable.
80*92ee37ffSKamlesh Gurudasani */
ti_device_set_state(struct ti_device * device_ptr,uint8_t host_idx,bool enable)81*92ee37ffSKamlesh Gurudasani void ti_device_set_state(struct ti_device *device_ptr, uint8_t host_idx, bool enable)
82*92ee37ffSKamlesh Gurudasani {
83*92ee37ffSKamlesh Gurudasani bool was_enabled;
84*92ee37ffSKamlesh Gurudasani bool is_enabled;
85*92ee37ffSKamlesh Gurudasani
86*92ee37ffSKamlesh Gurudasani assert(device_ptr != NULL);
87*92ee37ffSKamlesh Gurudasani assert((TI_DEV_FLAG_ENABLED(host_idx) & TI_DEV_FLAG_ENABLED_MASK) != 0UL);
88*92ee37ffSKamlesh Gurudasani
89*92ee37ffSKamlesh Gurudasani was_enabled = (device_ptr->flags & TI_DEV_FLAG_ENABLED_MASK) != 0UL;
90*92ee37ffSKamlesh Gurudasani
91*92ee37ffSKamlesh Gurudasani if (enable) {
92*92ee37ffSKamlesh Gurudasani device_ptr->flags |= (uint32_t)TI_DEV_FLAG_ENABLED(host_idx);
93*92ee37ffSKamlesh Gurudasani } else {
94*92ee37ffSKamlesh Gurudasani device_ptr->flags &= ~(uint32_t)TI_DEV_FLAG_ENABLED(host_idx);
95*92ee37ffSKamlesh Gurudasani }
96*92ee37ffSKamlesh Gurudasani
97*92ee37ffSKamlesh Gurudasani /*
98*92ee37ffSKamlesh Gurudasani * As soon as any host gets or puts a device, we drop the power
99*92ee37ffSKamlesh Gurudasani * on enabled flag.
100*92ee37ffSKamlesh Gurudasani */
101*92ee37ffSKamlesh Gurudasani if (host_idx != TI_DEV_POWER_ON_ENABLED_HOST_IDX) {
102*92ee37ffSKamlesh Gurudasani device_ptr->flags &= ~(uint32_t)TI_DEV_FLAG_POWER_ON_ENABLED;
103*92ee37ffSKamlesh Gurudasani }
104*92ee37ffSKamlesh Gurudasani
105*92ee37ffSKamlesh Gurudasani is_enabled = (device_ptr->flags & TI_DEV_FLAG_ENABLED_MASK) != 0UL;
106*92ee37ffSKamlesh Gurudasani if (was_enabled != is_enabled) {
107*92ee37ffSKamlesh Gurudasani if (is_enabled) {
108*92ee37ffSKamlesh Gurudasani device_enable(device_ptr);
109*92ee37ffSKamlesh Gurudasani } else {
110*92ee37ffSKamlesh Gurudasani ti_device_disable(device_ptr, false);
111*92ee37ffSKamlesh Gurudasani }
112*92ee37ffSKamlesh Gurudasani }
113*92ee37ffSKamlesh Gurudasani }
114*92ee37ffSKamlesh Gurudasani
115*92ee37ffSKamlesh Gurudasani /**
116*92ee37ffSKamlesh Gurudasani * ti_device_set_retention() - Enable or disable device retention.
117*92ee37ffSKamlesh Gurudasani * @device_ptr: The device to modify.
118*92ee37ffSKamlesh Gurudasani * @retention: True to enable retention, false to disable.
119*92ee37ffSKamlesh Gurudasani */
ti_device_set_retention(struct ti_device * device_ptr,bool retention)120*92ee37ffSKamlesh Gurudasani void ti_device_set_retention(struct ti_device *device_ptr, bool retention)
121*92ee37ffSKamlesh Gurudasani {
122*92ee37ffSKamlesh Gurudasani bool is_retention;
123*92ee37ffSKamlesh Gurudasani
124*92ee37ffSKamlesh Gurudasani assert(device_ptr != NULL);
125*92ee37ffSKamlesh Gurudasani
126*92ee37ffSKamlesh Gurudasani is_retention = ((device_ptr->flags & TI_DEV_FLAG_RETENTION) != 0U);
127*92ee37ffSKamlesh Gurudasani
128*92ee37ffSKamlesh Gurudasani if (retention == is_retention) {
129*92ee37ffSKamlesh Gurudasani return;
130*92ee37ffSKamlesh Gurudasani }
131*92ee37ffSKamlesh Gurudasani
132*92ee37ffSKamlesh Gurudasani if (retention) {
133*92ee37ffSKamlesh Gurudasani device_ptr->flags |= (uint32_t)TI_DEV_FLAG_RETENTION;
134*92ee37ffSKamlesh Gurudasani ti_soc_device_ret_enable(device_ptr);
135*92ee37ffSKamlesh Gurudasani } else {
136*92ee37ffSKamlesh Gurudasani device_ptr->flags &= ~(uint32_t)TI_DEV_FLAG_RETENTION;
137*92ee37ffSKamlesh Gurudasani ti_soc_device_ret_disable(device_ptr);
138*92ee37ffSKamlesh Gurudasani }
139*92ee37ffSKamlesh Gurudasani }
140