1 /* 2 * PRCC clock implementation for ux500 platform. 3 * 4 * Copyright (C) 2012 ST-Ericsson SA 5 * Author: Ulf Hansson <ulf.hansson@linaro.org> 6 * 7 * License terms: GNU General Public License (GPL) version 2 8 */ 9 10 #include <linux/clk-provider.h> 11 #include <linux/clk-private.h> 12 #include <linux/slab.h> 13 #include <linux/io.h> 14 #include <linux/err.h> 15 #include <linux/types.h> 16 17 #include "clk.h" 18 19 #define PRCC_PCKEN 0x000 20 #define PRCC_PCKDIS 0x004 21 #define PRCC_KCKEN 0x008 22 #define PRCC_KCKDIS 0x00C 23 #define PRCC_PCKSR 0x010 24 #define PRCC_KCKSR 0x014 25 26 #define to_clk_prcc(_hw) container_of(_hw, struct clk_prcc, hw) 27 28 struct clk_prcc { 29 struct clk_hw hw; 30 void __iomem *base; 31 u32 cg_sel; 32 int is_enabled; 33 }; 34 35 /* PRCC clock operations. */ 36 37 static int clk_prcc_pclk_enable(struct clk_hw *hw) 38 { 39 struct clk_prcc *clk = to_clk_prcc(hw); 40 41 writel(clk->cg_sel, (clk->base + PRCC_PCKEN)); 42 while (!(readl(clk->base + PRCC_PCKSR) & clk->cg_sel)) 43 cpu_relax(); 44 45 clk->is_enabled = 1; 46 return 0; 47 } 48 49 static void clk_prcc_pclk_disable(struct clk_hw *hw) 50 { 51 struct clk_prcc *clk = to_clk_prcc(hw); 52 53 writel(clk->cg_sel, (clk->base + PRCC_PCKDIS)); 54 clk->is_enabled = 0; 55 } 56 57 static int clk_prcc_kclk_enable(struct clk_hw *hw) 58 { 59 struct clk_prcc *clk = to_clk_prcc(hw); 60 61 writel(clk->cg_sel, (clk->base + PRCC_KCKEN)); 62 while (!(readl(clk->base + PRCC_KCKSR) & clk->cg_sel)) 63 cpu_relax(); 64 65 clk->is_enabled = 1; 66 return 0; 67 } 68 69 static void clk_prcc_kclk_disable(struct clk_hw *hw) 70 { 71 struct clk_prcc *clk = to_clk_prcc(hw); 72 73 writel(clk->cg_sel, (clk->base + PRCC_KCKDIS)); 74 clk->is_enabled = 0; 75 } 76 77 static int clk_prcc_is_enabled(struct clk_hw *hw) 78 { 79 struct clk_prcc *clk = to_clk_prcc(hw); 80 return clk->is_enabled; 81 } 82 83 static struct clk_ops clk_prcc_pclk_ops = { 84 .enable = clk_prcc_pclk_enable, 85 .disable = clk_prcc_pclk_disable, 86 .is_enabled = clk_prcc_is_enabled, 87 }; 88 89 static struct clk_ops clk_prcc_kclk_ops = { 90 .enable = clk_prcc_kclk_enable, 91 .disable = clk_prcc_kclk_disable, 92 .is_enabled = clk_prcc_is_enabled, 93 }; 94 95 static struct clk *clk_reg_prcc(const char *name, 96 const char *parent_name, 97 resource_size_t phy_base, 98 u32 cg_sel, 99 unsigned long flags, 100 struct clk_ops *clk_prcc_ops) 101 { 102 struct clk_prcc *clk; 103 struct clk_init_data clk_prcc_init; 104 struct clk *clk_reg; 105 106 if (!name) { 107 pr_err("clk_prcc: %s invalid arguments passed\n", __func__); 108 return ERR_PTR(-EINVAL); 109 } 110 111 clk = kzalloc(sizeof(struct clk_prcc), GFP_KERNEL); 112 if (!clk) { 113 pr_err("clk_prcc: %s could not allocate clk\n", __func__); 114 return ERR_PTR(-ENOMEM); 115 } 116 117 clk->base = ioremap(phy_base, SZ_4K); 118 if (!clk->base) 119 goto free_clk; 120 121 clk->cg_sel = cg_sel; 122 clk->is_enabled = 1; 123 124 clk_prcc_init.name = name; 125 clk_prcc_init.ops = clk_prcc_ops; 126 clk_prcc_init.flags = flags; 127 clk_prcc_init.parent_names = (parent_name ? &parent_name : NULL); 128 clk_prcc_init.num_parents = (parent_name ? 1 : 0); 129 clk->hw.init = &clk_prcc_init; 130 131 clk_reg = clk_register(NULL, &clk->hw); 132 if (IS_ERR_OR_NULL(clk_reg)) 133 goto unmap_clk; 134 135 return clk_reg; 136 137 unmap_clk: 138 iounmap(clk->base); 139 free_clk: 140 kfree(clk); 141 pr_err("clk_prcc: %s failed to register clk\n", __func__); 142 return ERR_PTR(-ENOMEM); 143 } 144 145 struct clk *clk_reg_prcc_pclk(const char *name, 146 const char *parent_name, 147 resource_size_t phy_base, 148 u32 cg_sel, 149 unsigned long flags) 150 { 151 return clk_reg_prcc(name, parent_name, phy_base, cg_sel, flags, 152 &clk_prcc_pclk_ops); 153 } 154 155 struct clk *clk_reg_prcc_kclk(const char *name, 156 const char *parent_name, 157 resource_size_t phy_base, 158 u32 cg_sel, 159 unsigned long flags) 160 { 161 return clk_reg_prcc(name, parent_name, phy_base, cg_sel, flags, 162 &clk_prcc_kclk_ops); 163 } 164