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 PLL Control Driver
9 *
10 * This driver provides low-level control for PLL enable/disable and lock
11 * status monitoring. It manages PLL control registers including PLLEN
12 * (PLL enable), PLLENSRC (enable source select), and PLLSTAT (lock status).
13 * The driver also implements mux functionality for PLL bypass/lock-based
14 * clock path selection.
15 */
16
17 #include <assert.h>
18
19 #include <lib/mmio.h>
20
21 #include <ti_clk_pllctrl.h>
22 #include <ti_container_of.h>
23
24 #define PLLCTRL_PLLCTRL 0x100U
25 #define PLLCTRL_PLLCTRL_PLLEN BIT(0)
26 #define PLLCTRL_PLLCTRL_PLLENSRC BIT(5)
27
28 #define PLLCTRL_PLLSTAT 0x13cU
29 #define PLLCTRL_PLLSTAT_LOCK BIT(1)
30
ti_clk_pllctrl_mux_get_parent(struct ti_clk * clkp)31 static const struct ti_clk_parent *ti_clk_pllctrl_mux_get_parent(struct ti_clk *clkp)
32 {
33 const struct ti_clk_data_mux *mux;
34 const struct ti_clk_data_mux_reg *reg;
35 const struct ti_clk_parent *parent = NULL;
36 uint32_t reg_val;
37
38 assert(clkp != NULL);
39
40 mux = ti_container_of(clkp->data, const struct ti_clk_data_mux, data);
41 reg = ti_container_of(mux, const struct ti_clk_data_mux_reg, data_mux);
42
43 reg_val = (uint32_t)mmio_read_32(reg->reg + PLLCTRL_PLLCTRL);
44 if ((reg_val & PLLCTRL_PLLCTRL_PLLENSRC) != 0U) {
45 /* When set, mux is controlled by lock state of PLL */
46 reg_val = (uint32_t)mmio_read_32(reg->reg + PLLCTRL_PLLSTAT);
47 if ((reg_val & PLLCTRL_PLLSTAT_LOCK) != 0U) {
48 /* PLL is locked */
49 parent = &mux->parents[1];
50 } else {
51 /* PLL is in bypass */
52 parent = &mux->parents[0];
53 }
54 } else {
55 /* When cleaned, mux is controlled by PLLEN bit */
56 if ((reg_val & PLLCTRL_PLLCTRL_PLLEN) != 0U) {
57 /* Use pll clock */
58 parent = &mux->parents[1];
59 } else {
60 /* Use bypass clock */
61 parent = &mux->parents[0];
62 }
63 }
64
65 /* If div is 0, parent clock is not connected */
66 if ((parent != NULL) && (parent->div == 0U)) {
67 parent = NULL;
68 }
69
70 return parent;
71 }
72
73 const struct ti_clk_drv_mux ti_clk_drv_pllctrl_mux_reg_ro = {
74 .get_parent = ti_clk_pllctrl_mux_get_parent,
75 };
76