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 * TI Device Clock Driver
9 *
10 * This driver provides clock nodes that are derived from device states,
11 * allowing the clock framework to query and track device power states.
12 * It implements a clock driver that reports frequency and state based on
13 * the associated device's power state, enabling clock tree dependencies
14 * on device power domains.
15 */
16
17 #include <assert.h>
18
19 #include <ti_clk.h>
20 #include <ti_clk_dev.h>
21 #include <ti_container_of.h>
22 #include <ti_device.h>
23 #include <ti_device_clk.h>
24 #include <ti_device_pm.h>
25
26 /**
27 * ti_clk_from_device_set_state() - Set the state of a device-derived clock.
28 * @clkp: The clock instance (unused).
29 * @enabled: True to enable, false to disable (unused).
30 *
31 * This clock's state is derived from the associated device's power domain
32 * and cannot be directly controlled via the clock framework; the device
33 * power state drives enablement, so always return success.
34 *
35 * Return: Always true.
36 */
ti_clk_from_device_set_state(struct ti_clk * clkp __maybe_unused,bool enabled __maybe_unused)37 static bool ti_clk_from_device_set_state(struct ti_clk *clkp __maybe_unused,
38 bool enabled __maybe_unused)
39 {
40 assert(clkp != NULL);
41
42 return true;
43 }
44
ti_clk_from_device_get_state(struct ti_clk * clkp)45 static uint32_t ti_clk_from_device_get_state(struct ti_clk *clkp)
46 {
47 const struct ti_clk_data_from_dev *from_device;
48 struct ti_dev_clk *dev_clkp;
49 struct ti_device *dev;
50 uint32_t state;
51
52 assert(clkp != NULL);
53
54 from_device = ti_container_of((const struct ti_clk_drv_data *)clkp->data,
55 const struct ti_clk_data_from_dev, data);
56
57 dev = ti_device_lookup(from_device->dev);
58 if ((dev == NULL) || (dev->initialized == 0U)) {
59 return TI_CLK_HW_STATE_DISABLED;
60 }
61
62 state = ti_device_get_state(dev);
63 if (state == TI_DEVICE_STATE_DISABLED) {
64 return TI_CLK_HW_STATE_DISABLED;
65 }
66
67 if (state == TI_DEVICE_STATE_TRANSITIONING) {
68 return TI_CLK_HW_STATE_TRANSITION;
69 }
70
71 dev_clkp = ti_get_dev_clk(dev, from_device->clk_idx);
72 if ((dev_clkp == NULL) || ((dev_clkp->flags & TI_DEV_CLK_FLAG_DISABLE) != 0U)) {
73 return TI_CLK_HW_STATE_DISABLED;
74 }
75
76 return TI_CLK_HW_STATE_ENABLED;
77 }
78
79 const struct ti_clk_drv ti_clk_drv_from_device = {
80 .get_freq = ti_clk_value_get_freq,
81 .set_state = ti_clk_from_device_set_state,
82 .get_state = ti_clk_from_device_get_state,
83 };
84