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