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