1 /* 2 * Helper routines for SuperH Clock Pulse Generator blocks (CPG). 3 * 4 * Copyright (C) 2010 Magnus Damm 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file "COPYING" in the main directory of this archive 8 * for more details. 9 */ 10 #include <linux/clk.h> 11 #include <linux/compiler.h> 12 #include <linux/slab.h> 13 #include <linux/io.h> 14 #include <linux/sh_clk.h> 15 16 static int sh_clk_mstp32_enable(struct clk *clk) 17 { 18 __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit), 19 clk->enable_reg); 20 return 0; 21 } 22 23 static void sh_clk_mstp32_disable(struct clk *clk) 24 { 25 __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit), 26 clk->enable_reg); 27 } 28 29 static struct clk_ops sh_clk_mstp32_clk_ops = { 30 .enable = sh_clk_mstp32_enable, 31 .disable = sh_clk_mstp32_disable, 32 .recalc = followparent_recalc, 33 }; 34 35 int __init sh_clk_mstp32_register(struct clk *clks, int nr) 36 { 37 struct clk *clkp; 38 int ret = 0; 39 int k; 40 41 for (k = 0; !ret && (k < nr); k++) { 42 clkp = clks + k; 43 clkp->ops = &sh_clk_mstp32_clk_ops; 44 ret |= clk_register(clkp); 45 } 46 47 return ret; 48 } 49 50 static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate) 51 { 52 return clk_rate_table_round(clk, clk->freq_table, rate); 53 } 54 55 static int sh_clk_div6_divisors[64] = { 56 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 57 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 58 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 59 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 60 }; 61 62 static struct clk_div_mult_table sh_clk_div6_table = { 63 .divisors = sh_clk_div6_divisors, 64 .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors), 65 }; 66 67 static unsigned long sh_clk_div6_recalc(struct clk *clk) 68 { 69 struct clk_div_mult_table *table = &sh_clk_div6_table; 70 unsigned int idx; 71 72 clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, 73 table, NULL); 74 75 idx = __raw_readl(clk->enable_reg) & 0x003f; 76 77 return clk->freq_table[idx].frequency; 78 } 79 80 static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent) 81 { 82 struct clk_div_mult_table *table = &sh_clk_div6_table; 83 u32 value; 84 int ret, i; 85 86 if (!clk->parent_table || !clk->parent_num) 87 return -EINVAL; 88 89 /* Search the parent */ 90 for (i = 0; i < clk->parent_num; i++) 91 if (clk->parent_table[i] == parent) 92 break; 93 94 if (i == clk->parent_num) 95 return -ENODEV; 96 97 ret = clk_reparent(clk, parent); 98 if (ret < 0) 99 return ret; 100 101 value = __raw_readl(clk->enable_reg) & 102 ~(((1 << clk->src_width) - 1) << clk->src_shift); 103 104 __raw_writel(value | (i << clk->src_shift), clk->enable_reg); 105 106 /* Rebuild the frequency table */ 107 clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, 108 table, &clk->arch_flags); 109 110 return 0; 111 } 112 113 static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate) 114 { 115 unsigned long value; 116 int idx; 117 118 idx = clk_rate_table_find(clk, clk->freq_table, rate); 119 if (idx < 0) 120 return idx; 121 122 value = __raw_readl(clk->enable_reg); 123 value &= ~0x3f; 124 value |= idx; 125 __raw_writel(value, clk->enable_reg); 126 return 0; 127 } 128 129 static int sh_clk_div6_enable(struct clk *clk) 130 { 131 unsigned long value; 132 int ret; 133 134 ret = sh_clk_div6_set_rate(clk, clk->rate); 135 if (ret == 0) { 136 value = __raw_readl(clk->enable_reg); 137 value &= ~0x100; /* clear stop bit to enable clock */ 138 __raw_writel(value, clk->enable_reg); 139 } 140 return ret; 141 } 142 143 static void sh_clk_div6_disable(struct clk *clk) 144 { 145 unsigned long value; 146 147 value = __raw_readl(clk->enable_reg); 148 value |= 0x100; /* stop clock */ 149 value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */ 150 __raw_writel(value, clk->enable_reg); 151 } 152 153 static struct clk_ops sh_clk_div6_clk_ops = { 154 .recalc = sh_clk_div6_recalc, 155 .round_rate = sh_clk_div_round_rate, 156 .set_rate = sh_clk_div6_set_rate, 157 .enable = sh_clk_div6_enable, 158 .disable = sh_clk_div6_disable, 159 }; 160 161 static struct clk_ops sh_clk_div6_reparent_clk_ops = { 162 .recalc = sh_clk_div6_recalc, 163 .round_rate = sh_clk_div_round_rate, 164 .set_rate = sh_clk_div6_set_rate, 165 .enable = sh_clk_div6_enable, 166 .disable = sh_clk_div6_disable, 167 .set_parent = sh_clk_div6_set_parent, 168 }; 169 170 static int __init sh_clk_div6_register_ops(struct clk *clks, int nr, 171 struct clk_ops *ops) 172 { 173 struct clk *clkp; 174 void *freq_table; 175 int nr_divs = sh_clk_div6_table.nr_divisors; 176 int freq_table_size = sizeof(struct cpufreq_frequency_table); 177 int ret = 0; 178 int k; 179 180 freq_table_size *= (nr_divs + 1); 181 freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL); 182 if (!freq_table) { 183 pr_err("sh_clk_div6_register: unable to alloc memory\n"); 184 return -ENOMEM; 185 } 186 187 for (k = 0; !ret && (k < nr); k++) { 188 clkp = clks + k; 189 190 clkp->ops = ops; 191 clkp->freq_table = freq_table + (k * freq_table_size); 192 clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; 193 194 ret = clk_register(clkp); 195 } 196 197 return ret; 198 } 199 200 int __init sh_clk_div6_register(struct clk *clks, int nr) 201 { 202 return sh_clk_div6_register_ops(clks, nr, &sh_clk_div6_clk_ops); 203 } 204 205 int __init sh_clk_div6_reparent_register(struct clk *clks, int nr) 206 { 207 return sh_clk_div6_register_ops(clks, nr, 208 &sh_clk_div6_reparent_clk_ops); 209 } 210 211 static unsigned long sh_clk_div4_recalc(struct clk *clk) 212 { 213 struct clk_div4_table *d4t = clk->priv; 214 struct clk_div_mult_table *table = d4t->div_mult_table; 215 unsigned int idx; 216 217 clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, 218 table, &clk->arch_flags); 219 220 idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f; 221 222 return clk->freq_table[idx].frequency; 223 } 224 225 static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) 226 { 227 struct clk_div4_table *d4t = clk->priv; 228 struct clk_div_mult_table *table = d4t->div_mult_table; 229 u32 value; 230 int ret; 231 232 /* we really need a better way to determine parent index, but for 233 * now assume internal parent comes with CLK_ENABLE_ON_INIT set, 234 * no CLK_ENABLE_ON_INIT means external clock... 235 */ 236 237 if (parent->flags & CLK_ENABLE_ON_INIT) 238 value = __raw_readl(clk->enable_reg) & ~(1 << 7); 239 else 240 value = __raw_readl(clk->enable_reg) | (1 << 7); 241 242 ret = clk_reparent(clk, parent); 243 if (ret < 0) 244 return ret; 245 246 __raw_writel(value, clk->enable_reg); 247 248 /* Rebiuld the frequency table */ 249 clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, 250 table, &clk->arch_flags); 251 252 return 0; 253 } 254 255 static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate) 256 { 257 struct clk_div4_table *d4t = clk->priv; 258 unsigned long value; 259 int idx = clk_rate_table_find(clk, clk->freq_table, rate); 260 if (idx < 0) 261 return idx; 262 263 value = __raw_readl(clk->enable_reg); 264 value &= ~(0xf << clk->enable_bit); 265 value |= (idx << clk->enable_bit); 266 __raw_writel(value, clk->enable_reg); 267 268 if (d4t->kick) 269 d4t->kick(clk); 270 271 return 0; 272 } 273 274 static int sh_clk_div4_enable(struct clk *clk) 275 { 276 __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg); 277 return 0; 278 } 279 280 static void sh_clk_div4_disable(struct clk *clk) 281 { 282 __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg); 283 } 284 285 static struct clk_ops sh_clk_div4_clk_ops = { 286 .recalc = sh_clk_div4_recalc, 287 .set_rate = sh_clk_div4_set_rate, 288 .round_rate = sh_clk_div_round_rate, 289 }; 290 291 static struct clk_ops sh_clk_div4_enable_clk_ops = { 292 .recalc = sh_clk_div4_recalc, 293 .set_rate = sh_clk_div4_set_rate, 294 .round_rate = sh_clk_div_round_rate, 295 .enable = sh_clk_div4_enable, 296 .disable = sh_clk_div4_disable, 297 }; 298 299 static struct clk_ops sh_clk_div4_reparent_clk_ops = { 300 .recalc = sh_clk_div4_recalc, 301 .set_rate = sh_clk_div4_set_rate, 302 .round_rate = sh_clk_div_round_rate, 303 .enable = sh_clk_div4_enable, 304 .disable = sh_clk_div4_disable, 305 .set_parent = sh_clk_div4_set_parent, 306 }; 307 308 static int __init sh_clk_div4_register_ops(struct clk *clks, int nr, 309 struct clk_div4_table *table, struct clk_ops *ops) 310 { 311 struct clk *clkp; 312 void *freq_table; 313 int nr_divs = table->div_mult_table->nr_divisors; 314 int freq_table_size = sizeof(struct cpufreq_frequency_table); 315 int ret = 0; 316 int k; 317 318 freq_table_size *= (nr_divs + 1); 319 freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL); 320 if (!freq_table) { 321 pr_err("sh_clk_div4_register: unable to alloc memory\n"); 322 return -ENOMEM; 323 } 324 325 for (k = 0; !ret && (k < nr); k++) { 326 clkp = clks + k; 327 328 clkp->ops = ops; 329 clkp->priv = table; 330 331 clkp->freq_table = freq_table + (k * freq_table_size); 332 clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; 333 334 ret = clk_register(clkp); 335 } 336 337 return ret; 338 } 339 340 int __init sh_clk_div4_register(struct clk *clks, int nr, 341 struct clk_div4_table *table) 342 { 343 return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div4_clk_ops); 344 } 345 346 int __init sh_clk_div4_enable_register(struct clk *clks, int nr, 347 struct clk_div4_table *table) 348 { 349 return sh_clk_div4_register_ops(clks, nr, table, 350 &sh_clk_div4_enable_clk_ops); 351 } 352 353 int __init sh_clk_div4_reparent_register(struct clk *clks, int nr, 354 struct clk_div4_table *table) 355 { 356 return sh_clk_div4_register_ops(clks, nr, table, 357 &sh_clk_div4_reparent_clk_ops); 358 } 359