1 #include <linux/clk.h> 2 #include <linux/err.h> 3 #include <linux/of.h> 4 #include <linux/slab.h> 5 #include <linux/spinlock.h> 6 #include "clk.h" 7 8 DEFINE_SPINLOCK(imx_ccm_lock); 9 10 void __init imx_check_clocks(struct clk *clks[], unsigned int count) 11 { 12 unsigned i; 13 14 for (i = 0; i < count; i++) 15 if (IS_ERR(clks[i])) 16 pr_err("i.MX clk %u: register failed with %ld\n", 17 i, PTR_ERR(clks[i])); 18 } 19 20 static struct clk * __init imx_obtain_fixed_clock_from_dt(const char *name) 21 { 22 struct of_phandle_args phandle; 23 struct clk *clk = ERR_PTR(-ENODEV); 24 char *path; 25 26 path = kasprintf(GFP_KERNEL, "/clocks/%s", name); 27 if (!path) 28 return ERR_PTR(-ENOMEM); 29 30 phandle.np = of_find_node_by_path(path); 31 kfree(path); 32 33 if (phandle.np) { 34 clk = of_clk_get_from_provider(&phandle); 35 of_node_put(phandle.np); 36 } 37 return clk; 38 } 39 40 struct clk * __init imx_obtain_fixed_clock( 41 const char *name, unsigned long rate) 42 { 43 struct clk *clk; 44 45 clk = imx_obtain_fixed_clock_from_dt(name); 46 if (IS_ERR(clk)) 47 clk = imx_clk_fixed(name, rate); 48 return clk; 49 } 50 51 /* 52 * This fixups the register CCM_CSCMR1 write value. 53 * The write/read/divider values of the aclk_podf field 54 * of that register have the relationship described by 55 * the following table: 56 * 57 * write value read value divider 58 * 3b'000 3b'110 7 59 * 3b'001 3b'111 8 60 * 3b'010 3b'100 5 61 * 3b'011 3b'101 6 62 * 3b'100 3b'010 3 63 * 3b'101 3b'011 4 64 * 3b'110 3b'000 1 65 * 3b'111 3b'001 2(default) 66 * 67 * That's why we do the xor operation below. 68 */ 69 #define CSCMR1_FIXUP 0x00600000 70 71 void imx_cscmr1_fixup(u32 *val) 72 { 73 *val ^= CSCMR1_FIXUP; 74 return; 75 } 76 77 static int imx_keep_uart_clocks __initdata; 78 static struct clk ** const *imx_uart_clocks __initdata; 79 80 static int __init imx_keep_uart_clocks_param(char *str) 81 { 82 imx_keep_uart_clocks = 1; 83 84 return 0; 85 } 86 __setup_param("earlycon", imx_keep_uart_earlycon, 87 imx_keep_uart_clocks_param, 0); 88 __setup_param("earlyprintk", imx_keep_uart_earlyprintk, 89 imx_keep_uart_clocks_param, 0); 90 91 void __init imx_register_uart_clocks(struct clk ** const clks[]) 92 { 93 if (imx_keep_uart_clocks) { 94 int i; 95 96 imx_uart_clocks = clks; 97 for (i = 0; imx_uart_clocks[i]; i++) 98 clk_prepare_enable(*imx_uart_clocks[i]); 99 } 100 } 101 102 static int __init imx_clk_disable_uart(void) 103 { 104 if (imx_keep_uart_clocks && imx_uart_clocks) { 105 int i; 106 107 for (i = 0; imx_uart_clocks[i]; i++) 108 clk_disable_unprepare(*imx_uart_clocks[i]); 109 } 110 111 return 0; 112 } 113 late_initcall_sync(imx_clk_disable_uart); 114