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