1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun #include <linux/kernel.h>
4*4882a593Smuzhiyun #include <linux/clk.h>
5*4882a593Smuzhiyun #include <linux/clk-provider.h>
6*4882a593Smuzhiyun #include <linux/clk/ti.h>
7*4882a593Smuzhiyun #include <linux/of_platform.h>
8*4882a593Smuzhiyun #include <dt-bindings/clock/dm814.h>
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include "clock.h"
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun static const struct omap_clkctrl_reg_data dm814_default_clkctrl_regs[] __initconst = {
13*4882a593Smuzhiyun { DM814_USB_OTG_HS_CLKCTRL, NULL, CLKF_SW_SUP, "pll260dcoclkldo" },
14*4882a593Smuzhiyun { 0 },
15*4882a593Smuzhiyun };
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun static const struct omap_clkctrl_reg_data dm814_alwon_clkctrl_regs[] __initconst = {
18*4882a593Smuzhiyun { DM814_UART1_CLKCTRL, NULL, CLKF_SW_SUP, "sysclk10_ck" },
19*4882a593Smuzhiyun { DM814_UART2_CLKCTRL, NULL, CLKF_SW_SUP, "sysclk10_ck" },
20*4882a593Smuzhiyun { DM814_UART3_CLKCTRL, NULL, CLKF_SW_SUP, "sysclk10_ck" },
21*4882a593Smuzhiyun { DM814_GPIO1_CLKCTRL, NULL, CLKF_SW_SUP, "sysclk6_ck" },
22*4882a593Smuzhiyun { DM814_GPIO2_CLKCTRL, NULL, CLKF_SW_SUP, "sysclk6_ck" },
23*4882a593Smuzhiyun { DM814_I2C1_CLKCTRL, NULL, CLKF_SW_SUP, "sysclk10_ck" },
24*4882a593Smuzhiyun { DM814_I2C2_CLKCTRL, NULL, CLKF_SW_SUP, "sysclk10_ck" },
25*4882a593Smuzhiyun { DM814_WD_TIMER_CLKCTRL, NULL, CLKF_SW_SUP | CLKF_NO_IDLEST, "sysclk18_ck" },
26*4882a593Smuzhiyun { DM814_MCSPI1_CLKCTRL, NULL, CLKF_SW_SUP, "sysclk10_ck" },
27*4882a593Smuzhiyun { DM814_GPMC_CLKCTRL, NULL, CLKF_SW_SUP, "sysclk6_ck" },
28*4882a593Smuzhiyun { DM814_MPU_CLKCTRL, NULL, CLKF_SW_SUP, "mpu_ck" },
29*4882a593Smuzhiyun { DM814_RTC_CLKCTRL, NULL, CLKF_SW_SUP | CLKF_NO_IDLEST, "sysclk18_ck" },
30*4882a593Smuzhiyun { DM814_TPCC_CLKCTRL, NULL, CLKF_SW_SUP, "sysclk4_ck" },
31*4882a593Smuzhiyun { DM814_TPTC0_CLKCTRL, NULL, CLKF_SW_SUP, "sysclk4_ck" },
32*4882a593Smuzhiyun { DM814_TPTC1_CLKCTRL, NULL, CLKF_SW_SUP, "sysclk4_ck" },
33*4882a593Smuzhiyun { DM814_TPTC2_CLKCTRL, NULL, CLKF_SW_SUP, "sysclk4_ck" },
34*4882a593Smuzhiyun { DM814_TPTC3_CLKCTRL, NULL, CLKF_SW_SUP, "sysclk4_ck" },
35*4882a593Smuzhiyun { DM814_MMC1_CLKCTRL, NULL, CLKF_SW_SUP, "sysclk8_ck" },
36*4882a593Smuzhiyun { DM814_MMC2_CLKCTRL, NULL, CLKF_SW_SUP, "sysclk8_ck" },
37*4882a593Smuzhiyun { DM814_MMC3_CLKCTRL, NULL, CLKF_SW_SUP, "sysclk8_ck" },
38*4882a593Smuzhiyun { 0 },
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun static const struct
42*4882a593Smuzhiyun omap_clkctrl_reg_data dm814_alwon_ethernet_clkctrl_regs[] __initconst = {
43*4882a593Smuzhiyun { 0, NULL, CLKF_SW_SUP, "cpsw_125mhz_gclk" },
44*4882a593Smuzhiyun };
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun const struct omap_clkctrl_data dm814_clkctrl_data[] __initconst = {
47*4882a593Smuzhiyun { 0x48180500, dm814_default_clkctrl_regs },
48*4882a593Smuzhiyun { 0x48181400, dm814_alwon_clkctrl_regs },
49*4882a593Smuzhiyun { 0x481815d4, dm814_alwon_ethernet_clkctrl_regs },
50*4882a593Smuzhiyun { 0 },
51*4882a593Smuzhiyun };
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun static struct ti_dt_clk dm814_clks[] = {
54*4882a593Smuzhiyun DT_CLK(NULL, "timer_sys_ck", "devosc_ck"),
55*4882a593Smuzhiyun { .node_name = NULL },
56*4882a593Smuzhiyun };
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun static bool timer_clocks_initialized;
59*4882a593Smuzhiyun
dm814x_adpll_early_init(void)60*4882a593Smuzhiyun static int __init dm814x_adpll_early_init(void)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun struct device_node *np;
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun if (!timer_clocks_initialized)
65*4882a593Smuzhiyun return -ENODEV;
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun np = of_find_node_by_name(NULL, "pllss");
68*4882a593Smuzhiyun if (!np) {
69*4882a593Smuzhiyun pr_err("Could not find node for plls\n");
70*4882a593Smuzhiyun return -ENODEV;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun of_platform_populate(np, NULL, NULL, NULL);
74*4882a593Smuzhiyun of_node_put(np);
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun return 0;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun core_initcall(dm814x_adpll_early_init);
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun static const char * const init_clocks[] = {
81*4882a593Smuzhiyun "pll040clkout", /* MPU 481c5040.adpll.clkout */
82*4882a593Smuzhiyun "pll290clkout", /* DDR 481c5290.adpll.clkout */
83*4882a593Smuzhiyun };
84*4882a593Smuzhiyun
dm814x_adpll_enable_init_clocks(void)85*4882a593Smuzhiyun static int __init dm814x_adpll_enable_init_clocks(void)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun int i, err;
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun if (!timer_clocks_initialized)
90*4882a593Smuzhiyun return -ENODEV;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(init_clocks); i++) {
93*4882a593Smuzhiyun struct clk *clock;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun clock = clk_get(NULL, init_clocks[i]);
96*4882a593Smuzhiyun if (WARN(IS_ERR(clock), "could not find init clock %s\n",
97*4882a593Smuzhiyun init_clocks[i]))
98*4882a593Smuzhiyun continue;
99*4882a593Smuzhiyun err = clk_prepare_enable(clock);
100*4882a593Smuzhiyun if (WARN(err, "could not enable init clock %s\n",
101*4882a593Smuzhiyun init_clocks[i]))
102*4882a593Smuzhiyun continue;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun return 0;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun postcore_initcall(dm814x_adpll_enable_init_clocks);
108*4882a593Smuzhiyun
dm814x_dt_clk_init(void)109*4882a593Smuzhiyun int __init dm814x_dt_clk_init(void)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun ti_dt_clocks_register(dm814_clks);
112*4882a593Smuzhiyun omap2_clk_disable_autoidle_all();
113*4882a593Smuzhiyun ti_clk_add_aliases();
114*4882a593Smuzhiyun omap2_clk_enable_init_clocks(NULL, 0);
115*4882a593Smuzhiyun timer_clocks_initialized = true;
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun return 0;
118*4882a593Smuzhiyun }
119