clk-div6.c 6.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * r8a7790 Common Clock Framework support
 *
 * Copyright (C) 2013  Renesas Solutions Corp.
 *
 * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 */

#include <linux/clk-provider.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_address.h>
19
#include <linux/slab.h>
20 21 22 23 24 25

#define CPG_DIV6_CKSTP		BIT(8)
#define CPG_DIV6_DIV(d)		((d) & 0x3f)
#define CPG_DIV6_DIV_MASK	0x3f

/**
26
 * struct div6_clock - CPG 6 bit divider clock
27 28 29 30 31 32 33 34
 * @hw: handle between common and hardware-specific interfaces
 * @reg: IO-remapped register
 * @div: divisor value (1-64)
 */
struct div6_clock {
	struct clk_hw hw;
	void __iomem *reg;
	unsigned int div;
35 36 37
	u32 src_shift;
	u32 src_width;
	u8 *parents;
38 39 40 41 42 43 44
};

#define to_div6_clock(_hw) container_of(_hw, struct div6_clock, hw)

static int cpg_div6_clock_enable(struct clk_hw *hw)
{
	struct div6_clock *clock = to_div6_clock(hw);
45
	u32 val;
46

47 48 49
	val = (clk_readl(clock->reg) & ~(CPG_DIV6_DIV_MASK | CPG_DIV6_CKSTP))
	    | CPG_DIV6_DIV(clock->div - 1);
	clk_writel(val, clock->reg);
50 51 52 53 54 55 56

	return 0;
}

static void cpg_div6_clock_disable(struct clk_hw *hw)
{
	struct div6_clock *clock = to_div6_clock(hw);
57
	u32 val;
58

59 60 61 62 63 64 65
	val = clk_readl(clock->reg);
	val |= CPG_DIV6_CKSTP;
	/*
	 * DIV6 clocks require the divisor field to be non-zero when stopping
	 * the clock. However, some clocks (e.g. ZB on sh73a0) fail to be
	 * re-enabled later if the divisor field is changed when stopping the
	 * clock
66
	 */
67 68 69
	if (!(val & CPG_DIV6_DIV_MASK))
		val |= CPG_DIV6_DIV_MASK;
	clk_writel(val, clock->reg);
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
}

static int cpg_div6_clock_is_enabled(struct clk_hw *hw)
{
	struct div6_clock *clock = to_div6_clock(hw);

	return !(clk_readl(clock->reg) & CPG_DIV6_CKSTP);
}

static unsigned long cpg_div6_clock_recalc_rate(struct clk_hw *hw,
						unsigned long parent_rate)
{
	struct div6_clock *clock = to_div6_clock(hw);
	unsigned int div = (clk_readl(clock->reg) & CPG_DIV6_DIV_MASK) + 1;

	return parent_rate / div;
}

static unsigned int cpg_div6_clock_calc_div(unsigned long rate,
					    unsigned long parent_rate)
{
	unsigned int div;

93 94 95
	if (!rate)
		rate = 1;

96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
	div = DIV_ROUND_CLOSEST(parent_rate, rate);
	return clamp_t(unsigned int, div, 1, 64);
}

static long cpg_div6_clock_round_rate(struct clk_hw *hw, unsigned long rate,
				      unsigned long *parent_rate)
{
	unsigned int div = cpg_div6_clock_calc_div(rate, *parent_rate);

	return *parent_rate / div;
}

static int cpg_div6_clock_set_rate(struct clk_hw *hw, unsigned long rate,
				   unsigned long parent_rate)
{
	struct div6_clock *clock = to_div6_clock(hw);
	unsigned int div = cpg_div6_clock_calc_div(rate, parent_rate);
113
	u32 val;
114 115 116

	clock->div = div;

117
	val = clk_readl(clock->reg) & ~CPG_DIV6_DIV_MASK;
118
	/* Only program the new divisor if the clock isn't stopped. */
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
	if (!(val & CPG_DIV6_CKSTP))
		clk_writel(val | CPG_DIV6_DIV(clock->div - 1), clock->reg);

	return 0;
}

static u8 cpg_div6_clock_get_parent(struct clk_hw *hw)
{
	struct div6_clock *clock = to_div6_clock(hw);
	unsigned int i;
	u8 hw_index;

	if (clock->src_width == 0)
		return 0;

	hw_index = (clk_readl(clock->reg) >> clock->src_shift) &
		   (BIT(clock->src_width) - 1);
	for (i = 0; i < __clk_get_num_parents(hw->clk); i++) {
		if (clock->parents[i] == hw_index)
			return i;
	}

	pr_err("%s: %s DIV6 clock set to invalid parent %u\n",
	       __func__, __clk_get_name(hw->clk), hw_index);
	return 0;
}

static int cpg_div6_clock_set_parent(struct clk_hw *hw, u8 index)
{
	struct div6_clock *clock = to_div6_clock(hw);
	u8 hw_index;
	u32 mask;

	if (index >= __clk_get_num_parents(hw->clk))
		return -EINVAL;

	mask = ~((BIT(clock->src_width) - 1) << clock->src_shift);
	hw_index = clock->parents[index];

	clk_writel((clk_readl(clock->reg) & mask) |
		(hw_index << clock->src_shift), clock->reg);
160 161 162 163 164 165 166 167

	return 0;
}

static const struct clk_ops cpg_div6_clock_ops = {
	.enable = cpg_div6_clock_enable,
	.disable = cpg_div6_clock_disable,
	.is_enabled = cpg_div6_clock_is_enabled,
168 169
	.get_parent = cpg_div6_clock_get_parent,
	.set_parent = cpg_div6_clock_set_parent,
170 171 172 173 174 175 176
	.recalc_rate = cpg_div6_clock_recalc_rate,
	.round_rate = cpg_div6_clock_round_rate,
	.set_rate = cpg_div6_clock_set_rate,
};

static void __init cpg_div6_clock_init(struct device_node *np)
{
177 178
	unsigned int num_parents, valid_parents;
	const char **parent_names;
179 180 181 182
	struct clk_init_data init;
	struct div6_clock *clock;
	const char *name;
	struct clk *clk;
183
	unsigned int i;
184 185 186
	int ret;

	clock = kzalloc(sizeof(*clock), GFP_KERNEL);
187 188 189 190 191 192
	if (!clock)
		return;

	num_parents = of_clk_get_parent_count(np);
	if (num_parents < 1) {
		pr_err("%s: no parent found for %s DIV6 clock\n",
193 194 195 196
		       __func__, np->name);
		return;
	}

197 198 199 200 201 202 203
	clock->parents = kmalloc_array(num_parents, sizeof(*clock->parents),
		GFP_KERNEL);
	parent_names = kmalloc_array(num_parents, sizeof(*parent_names),
				GFP_KERNEL);
	if (!parent_names)
		return;

204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
	/* Remap the clock register and read the divisor. Disabling the
	 * clock overwrites the divisor, so we need to cache its value for the
	 * enable operation.
	 */
	clock->reg = of_iomap(np, 0);
	if (clock->reg == NULL) {
		pr_err("%s: failed to map %s DIV6 clock register\n",
		       __func__, np->name);
		goto error;
	}

	clock->div = (clk_readl(clock->reg) & CPG_DIV6_DIV_MASK) + 1;

	/* Parse the DT properties. */
	ret = of_property_read_string(np, "clock-output-names", &name);
	if (ret < 0) {
		pr_err("%s: failed to get %s DIV6 clock output name\n",
		       __func__, np->name);
		goto error;
	}

225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252

	for (i = 0, valid_parents = 0; i < num_parents; i++) {
		const char *name = of_clk_get_parent_name(np, i);

		if (name) {
			parent_names[valid_parents] = name;
			clock->parents[valid_parents] = i;
			valid_parents++;
		}
	}

	switch (num_parents) {
	case 1:
		/* fixed parent clock */
		clock->src_shift = clock->src_width = 0;
		break;
	case 4:
		/* clock with EXSRC bits 6-7 */
		clock->src_shift = 6;
		clock->src_width = 2;
		break;
	case 8:
		/* VCLK with EXSRC bits 12-14 */
		clock->src_shift = 12;
		clock->src_width = 3;
		break;
	default:
		pr_err("%s: invalid number of parents for DIV6 clock %s\n",
253 254 255 256 257 258 259 260
		       __func__, np->name);
		goto error;
	}

	/* Register the clock. */
	init.name = name;
	init.ops = &cpg_div6_clock_ops;
	init.flags = CLK_IS_BASIC;
261 262
	init.parent_names = parent_names;
	init.num_parents = valid_parents;
263 264 265 266 267 268 269 270 271 272 273 274

	clock->hw.init = &init;

	clk = clk_register(NULL, &clock->hw);
	if (IS_ERR(clk)) {
		pr_err("%s: failed to register %s DIV6 clock (%ld)\n",
		       __func__, np->name, PTR_ERR(clk));
		goto error;
	}

	of_clk_add_provider(np, of_clk_src_simple_get, clk);

275
	kfree(parent_names);
276 277 278 279 280
	return;

error:
	if (clock->reg)
		iounmap(clock->reg);
281
	kfree(parent_names);
282 283 284
	kfree(clock);
}
CLK_OF_DECLARE(cpg_div6_clk, "renesas,cpg-div6-clock", cpg_div6_clock_init);