xref: /openbmc/linux/drivers/clk/ti/clk-33xx.c (revision 7368b18d)
1 /*
2  * AM33XX Clock init
3  *
4  * Copyright (C) 2013 Texas Instruments, Inc
5  *     Tero Kristo (t-kristo@ti.com)
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation version 2.
10  *
11  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
12  * kind, whether express or implied; without even the implied warranty
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  */
16 
17 #include <linux/kernel.h>
18 #include <linux/list.h>
19 #include <linux/clk.h>
20 #include <linux/clk-provider.h>
21 #include <linux/clk/ti.h>
22 
23 #include "clock.h"
24 
25 static struct ti_dt_clk am33xx_clks[] = {
26 	DT_CLK(NULL, "timer_32k_ck", "clkdiv32k_ick"),
27 	DT_CLK(NULL, "timer_sys_ck", "sys_clkin_ck"),
28 	{ .node_name = NULL },
29 };
30 
31 static const char *enable_init_clks[] = {
32 	"dpll_ddr_m2_ck",
33 	"dpll_mpu_m2_ck",
34 	"l3_gclk",
35 	"l4hs_gclk",
36 	"l4fw_gclk",
37 	"l4ls_gclk",
38 	/* Required for external peripherals like, Audio codecs */
39 	"clkout2_ck",
40 };
41 
42 int __init am33xx_dt_clk_init(void)
43 {
44 	struct clk *clk1, *clk2;
45 
46 	ti_dt_clocks_register(am33xx_clks);
47 
48 	omap2_clk_disable_autoidle_all();
49 
50 	ti_clk_add_aliases();
51 
52 	omap2_clk_enable_init_clocks(enable_init_clks,
53 				     ARRAY_SIZE(enable_init_clks));
54 
55 	/* TRM ERRATA: Timer 3 & 6 default parent (TCLKIN) may not be always
56 	 *    physically present, in such a case HWMOD enabling of
57 	 *    clock would be failure with default parent. And timer
58 	 *    probe thinks clock is already enabled, this leads to
59 	 *    crash upon accessing timer 3 & 6 registers in probe.
60 	 *    Fix by setting parent of both these timers to master
61 	 *    oscillator clock.
62 	 */
63 
64 	clk1 = clk_get_sys(NULL, "sys_clkin_ck");
65 	clk2 = clk_get_sys(NULL, "timer3_fck");
66 	clk_set_parent(clk2, clk1);
67 
68 	clk2 = clk_get_sys(NULL, "timer6_fck");
69 	clk_set_parent(clk2, clk1);
70 	/*
71 	 * The On-Chip 32K RC Osc clock is not an accurate clock-source as per
72 	 * the design/spec, so as a result, for example, timer which supposed
73 	 * to get expired @60Sec, but will expire somewhere ~@40Sec, which is
74 	 * not expected by any use-case, so change WDT1 clock source to PRCM
75 	 * 32KHz clock.
76 	 */
77 	clk1 = clk_get_sys(NULL, "wdt1_fck");
78 	clk2 = clk_get_sys(NULL, "clkdiv32k_ick");
79 	clk_set_parent(clk1, clk2);
80 
81 	return 0;
82 }
83