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