1/* 2 * r8a7790 Common Clock Framework support 3 * 4 * Copyright (C) 2013 Renesas Solutions Corp. 5 * 6 * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; version 2 of the License. 11 */ 12 13#include <linux/clk-provider.h> 14#include <linux/clkdev.h> 15#include <linux/init.h> 16#include <linux/io.h> 17#include <linux/kernel.h> 18#include <linux/of.h> 19#include <linux/of_address.h> 20 21#define CPG_DIV6_CKSTP BIT(8) 22#define CPG_DIV6_DIV(d) ((d) & 0x3f) 23#define CPG_DIV6_DIV_MASK 0x3f 24 25/** 26 * struct div6_clock - CPG 6 bit divider clock 27 * @hw: handle between common and hardware-specific interfaces 28 * @reg: IO-remapped register 29 * @div: divisor value (1-64) 30 */ 31struct div6_clock { 32 struct clk_hw hw; 33 void __iomem *reg; 34 unsigned int div; 35 u32 src_shift; 36 u32 src_width; 37 u8 *parents; 38}; 39 40#define to_div6_clock(_hw) container_of(_hw, struct div6_clock, hw) 41 42static int cpg_div6_clock_enable(struct clk_hw *hw) 43{ 44 struct div6_clock *clock = to_div6_clock(hw); 45 u32 val; 46 47 val = (clk_readl(clock->reg) & ~(CPG_DIV6_DIV_MASK | CPG_DIV6_CKSTP)) 48 | CPG_DIV6_DIV(clock->div - 1); 49 clk_writel(val, clock->reg); 50 51 return 0; 52} 53 54static void cpg_div6_clock_disable(struct clk_hw *hw) 55{ 56 struct div6_clock *clock = to_div6_clock(hw); 57 u32 val; 58 59 val = clk_readl(clock->reg); 60 val |= CPG_DIV6_CKSTP; 61 /* 62 * DIV6 clocks require the divisor field to be non-zero when stopping 63 * the clock. However, some clocks (e.g. ZB on sh73a0) fail to be 64 * re-enabled later if the divisor field is changed when stopping the 65 * clock 66 */ 67 if (!(val & CPG_DIV6_DIV_MASK)) 68 val |= CPG_DIV6_DIV_MASK; 69 clk_writel(val, clock->reg); 70} 71 72static int cpg_div6_clock_is_enabled(struct clk_hw *hw) 73{ 74 struct div6_clock *clock = to_div6_clock(hw); 75 76 return !(clk_readl(clock->reg) & CPG_DIV6_CKSTP); 77} 78 79static unsigned long cpg_div6_clock_recalc_rate(struct clk_hw *hw, 80 unsigned long parent_rate) 81{ 82 struct div6_clock *clock = to_div6_clock(hw); 83 unsigned int div = (clk_readl(clock->reg) & CPG_DIV6_DIV_MASK) + 1; 84 85 return parent_rate / div; 86} 87 88static unsigned int cpg_div6_clock_calc_div(unsigned long rate, 89 unsigned long parent_rate) 90{ 91 unsigned int div; 92 93 if (!rate) 94 rate = 1; 95 96 div = DIV_ROUND_CLOSEST(parent_rate, rate); 97 return clamp_t(unsigned int, div, 1, 64); 98} 99 100static long cpg_div6_clock_round_rate(struct clk_hw *hw, unsigned long rate, 101 unsigned long *parent_rate) 102{ 103 unsigned int div = cpg_div6_clock_calc_div(rate, *parent_rate); 104 105 return *parent_rate / div; 106} 107 108static int cpg_div6_clock_set_rate(struct clk_hw *hw, unsigned long rate, 109 unsigned long parent_rate) 110{ 111 struct div6_clock *clock = to_div6_clock(hw); 112 unsigned int div = cpg_div6_clock_calc_div(rate, parent_rate); 113 u32 val; 114 115 clock->div = div; 116 117 val = clk_readl(clock->reg) & ~CPG_DIV6_DIV_MASK; 118 /* Only program the new divisor if the clock isn't stopped. */ 119 if (!(val & CPG_DIV6_CKSTP)) 120 clk_writel(val | CPG_DIV6_DIV(clock->div - 1), clock->reg); 121 122 return 0; 123} 124 125static u8 cpg_div6_clock_get_parent(struct clk_hw *hw) 126{ 127 struct div6_clock *clock = to_div6_clock(hw); 128 unsigned int i; 129 u8 hw_index; 130 131 if (clock->src_width == 0) 132 return 0; 133 134 hw_index = (clk_readl(clock->reg) >> clock->src_shift) & 135 (BIT(clock->src_width) - 1); 136 for (i = 0; i < __clk_get_num_parents(hw->clk); i++) { 137 if (clock->parents[i] == hw_index) 138 return i; 139 } 140 141 pr_err("%s: %s DIV6 clock set to invalid parent %u\n", 142 __func__, __clk_get_name(hw->clk), hw_index); 143 return 0; 144} 145 146static int cpg_div6_clock_set_parent(struct clk_hw *hw, u8 index) 147{ 148 struct div6_clock *clock = to_div6_clock(hw); 149 u8 hw_index; 150 u32 mask; 151 152 if (index >= __clk_get_num_parents(hw->clk)) 153 return -EINVAL; 154 155 mask = ~((BIT(clock->src_width) - 1) << clock->src_shift); 156 hw_index = clock->parents[index]; 157 158 clk_writel((clk_readl(clock->reg) & mask) | 159 (hw_index << clock->src_shift), clock->reg); 160 161 return 0; 162} 163 164static const struct clk_ops cpg_div6_clock_ops = { 165 .enable = cpg_div6_clock_enable, 166 .disable = cpg_div6_clock_disable, 167 .is_enabled = cpg_div6_clock_is_enabled, 168 .get_parent = cpg_div6_clock_get_parent, 169 .set_parent = cpg_div6_clock_set_parent, 170 .recalc_rate = cpg_div6_clock_recalc_rate, 171 .round_rate = cpg_div6_clock_round_rate, 172 .set_rate = cpg_div6_clock_set_rate, 173}; 174 175static void __init cpg_div6_clock_init(struct device_node *np) 176{ 177 unsigned int num_parents, valid_parents; 178 const char **parent_names; 179 struct clk_init_data init; 180 struct div6_clock *clock; 181 const char *name; 182 struct clk *clk; 183 unsigned int i; 184 int ret; 185 186 clock = kzalloc(sizeof(*clock), GFP_KERNEL); 187 if (!clock) 188 return; 189 190 num_parents = of_clk_get_parent_count(np); 191 if (num_parents < 1) { 192 pr_err("%s: no parent found for %s DIV6 clock\n", 193 __func__, np->name); 194 return; 195 } 196 197 clock->parents = kmalloc_array(num_parents, sizeof(*clock->parents), 198 GFP_KERNEL); 199 parent_names = kmalloc_array(num_parents, sizeof(*parent_names), 200 GFP_KERNEL); 201 if (!parent_names) 202 return; 203 204 /* Remap the clock register and read the divisor. Disabling the 205 * clock overwrites the divisor, so we need to cache its value for the 206 * enable operation. 207 */ 208 clock->reg = of_iomap(np, 0); 209 if (clock->reg == NULL) { 210 pr_err("%s: failed to map %s DIV6 clock register\n", 211 __func__, np->name); 212 goto error; 213 } 214 215 clock->div = (clk_readl(clock->reg) & CPG_DIV6_DIV_MASK) + 1; 216 217 /* Parse the DT properties. */ 218 ret = of_property_read_string(np, "clock-output-names", &name); 219 if (ret < 0) { 220 pr_err("%s: failed to get %s DIV6 clock output name\n", 221 __func__, np->name); 222 goto error; 223 } 224 225 226 for (i = 0, valid_parents = 0; i < num_parents; i++) { 227 const char *name = of_clk_get_parent_name(np, i); 228 229 if (name) { 230 parent_names[valid_parents] = name; 231 clock->parents[valid_parents] = i; 232 valid_parents++; 233 } 234 } 235 236 switch (num_parents) { 237 case 1: 238 /* fixed parent clock */ 239 clock->src_shift = clock->src_width = 0; 240 break; 241 case 4: 242 /* clock with EXSRC bits 6-7 */ 243 clock->src_shift = 6; 244 clock->src_width = 2; 245 break; 246 case 8: 247 /* VCLK with EXSRC bits 12-14 */ 248 clock->src_shift = 12; 249 clock->src_width = 3; 250 break; 251 default: 252 pr_err("%s: invalid number of parents for DIV6 clock %s\n", 253 __func__, np->name); 254 goto error; 255 } 256 257 /* Register the clock. */ 258 init.name = name; 259 init.ops = &cpg_div6_clock_ops; 260 init.flags = CLK_IS_BASIC; 261 init.parent_names = parent_names; 262 init.num_parents = valid_parents; 263 264 clock->hw.init = &init; 265 266 clk = clk_register(NULL, &clock->hw); 267 if (IS_ERR(clk)) { 268 pr_err("%s: failed to register %s DIV6 clock (%ld)\n", 269 __func__, np->name, PTR_ERR(clk)); 270 goto error; 271 } 272 273 of_clk_add_provider(np, of_clk_src_simple_get, clk); 274 275 kfree(parent_names); 276 return; 277 278error: 279 if (clock->reg) 280 iounmap(clock->reg); 281 kfree(parent_names); 282 kfree(clock); 283} 284CLK_OF_DECLARE(cpg_div6_clk, "renesas,cpg-div6-clock", cpg_div6_clock_init); 285