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 8DEFINE_SPINLOCK(imx_ccm_lock); 9 10void __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 20static 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 40struct 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 71void imx_cscmr1_fixup(u32 *val) 72{ 73 *val ^= CSCMR1_FIXUP; 74 return; 75} 76 77static int imx_keep_uart_clocks __initdata; 78static struct clk ** const *imx_uart_clocks __initdata; 79 80static 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 91void __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 102static 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} 113late_initcall_sync(imx_clk_disable_uart); 114