xref: /rk3399_ARM-atf/drivers/ti/pd/ti_device_pm.c (revision a28114d66a6d43db4accef5fd5d6dab6c059e584)
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