1 /* 2 * drivers/clk/at91/clk-slow.c 3 * 4 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 */ 12 13 #include <linux/clk-provider.h> 14 #include <linux/clkdev.h> 15 #include <linux/clk/at91_pmc.h> 16 #include <linux/of.h> 17 #include <linux/mfd/syscon.h> 18 #include <linux/regmap.h> 19 20 #include "pmc.h" 21 22 struct clk_sam9260_slow { 23 struct clk_hw hw; 24 struct regmap *regmap; 25 }; 26 27 #define to_clk_sam9260_slow(hw) container_of(hw, struct clk_sam9260_slow, hw) 28 29 static u8 clk_sam9260_slow_get_parent(struct clk_hw *hw) 30 { 31 struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(hw); 32 unsigned int status; 33 34 regmap_read(slowck->regmap, AT91_PMC_SR, &status); 35 36 return status & AT91_PMC_OSCSEL ? 1 : 0; 37 } 38 39 static const struct clk_ops sam9260_slow_ops = { 40 .get_parent = clk_sam9260_slow_get_parent, 41 }; 42 43 struct clk_hw * __init 44 at91_clk_register_sam9260_slow(struct regmap *regmap, 45 const char *name, 46 const char **parent_names, 47 int num_parents) 48 { 49 struct clk_sam9260_slow *slowck; 50 struct clk_hw *hw; 51 struct clk_init_data init; 52 int ret; 53 54 if (!name) 55 return ERR_PTR(-EINVAL); 56 57 if (!parent_names || !num_parents) 58 return ERR_PTR(-EINVAL); 59 60 slowck = kzalloc(sizeof(*slowck), GFP_KERNEL); 61 if (!slowck) 62 return ERR_PTR(-ENOMEM); 63 64 init.name = name; 65 init.ops = &sam9260_slow_ops; 66 init.parent_names = parent_names; 67 init.num_parents = num_parents; 68 init.flags = 0; 69 70 slowck->hw.init = &init; 71 slowck->regmap = regmap; 72 73 hw = &slowck->hw; 74 ret = clk_hw_register(NULL, &slowck->hw); 75 if (ret) { 76 kfree(slowck); 77 hw = ERR_PTR(ret); 78 } 79 80 return hw; 81 } 82