Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.2-rc4 108 lines 2.3 kB view raw
1/* 2 * Copyright (c) 2014 Lucas Stach <l.stach@pengutronix.de>, Pengutronix 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 * 8 * http://www.opensource.org/licenses/gpl-license.html 9 * http://www.gnu.org/copyleft/gpl.html 10 */ 11 12#include <linux/clk.h> 13#include <linux/clk-provider.h> 14#include <linux/slab.h> 15#include "clk.h" 16 17struct clk_cpu { 18 struct clk_hw hw; 19 struct clk *div; 20 struct clk *mux; 21 struct clk *pll; 22 struct clk *step; 23}; 24 25static inline struct clk_cpu *to_clk_cpu(struct clk_hw *hw) 26{ 27 return container_of(hw, struct clk_cpu, hw); 28} 29 30static unsigned long clk_cpu_recalc_rate(struct clk_hw *hw, 31 unsigned long parent_rate) 32{ 33 struct clk_cpu *cpu = to_clk_cpu(hw); 34 35 return clk_get_rate(cpu->div); 36} 37 38static long clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate, 39 unsigned long *prate) 40{ 41 struct clk_cpu *cpu = to_clk_cpu(hw); 42 43 return clk_round_rate(cpu->pll, rate); 44} 45 46static int clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate, 47 unsigned long parent_rate) 48{ 49 struct clk_cpu *cpu = to_clk_cpu(hw); 50 int ret; 51 52 /* switch to PLL bypass clock */ 53 ret = clk_set_parent(cpu->mux, cpu->step); 54 if (ret) 55 return ret; 56 57 /* reprogram PLL */ 58 ret = clk_set_rate(cpu->pll, rate); 59 if (ret) { 60 clk_set_parent(cpu->mux, cpu->pll); 61 return ret; 62 } 63 /* switch back to PLL clock */ 64 clk_set_parent(cpu->mux, cpu->pll); 65 66 /* Ensure the divider is what we expect */ 67 clk_set_rate(cpu->div, rate); 68 69 return 0; 70} 71 72static const struct clk_ops clk_cpu_ops = { 73 .recalc_rate = clk_cpu_recalc_rate, 74 .round_rate = clk_cpu_round_rate, 75 .set_rate = clk_cpu_set_rate, 76}; 77 78struct clk *imx_clk_cpu(const char *name, const char *parent_name, 79 struct clk *div, struct clk *mux, struct clk *pll, 80 struct clk *step) 81{ 82 struct clk_cpu *cpu; 83 struct clk *clk; 84 struct clk_init_data init; 85 86 cpu = kzalloc(sizeof(*cpu), GFP_KERNEL); 87 if (!cpu) 88 return ERR_PTR(-ENOMEM); 89 90 cpu->div = div; 91 cpu->mux = mux; 92 cpu->pll = pll; 93 cpu->step = step; 94 95 init.name = name; 96 init.ops = &clk_cpu_ops; 97 init.flags = 0; 98 init.parent_names = &parent_name; 99 init.num_parents = 1; 100 101 cpu->hw.init = &init; 102 103 clk = clk_register(NULL, &cpu->hw); 104 if (IS_ERR(clk)) 105 kfree(cpu); 106 107 return clk; 108}