xref: /rk3399_rockchip-uboot/arch/arm/cpu/armv7/bcm281xx/clk-core.c (revision 6def7de37ba2aeb3d59c561b288537d8c3712c73)
1989ce049SDarwin Rambo /*
2989ce049SDarwin Rambo  * Copyright 2013 Broadcom Corporation.
3989ce049SDarwin Rambo  *
4989ce049SDarwin Rambo  * SPDX-License-Identifier:      GPL-2.0+
5989ce049SDarwin Rambo  */
6989ce049SDarwin Rambo 
7989ce049SDarwin Rambo /*
8989ce049SDarwin Rambo  *
9989ce049SDarwin Rambo  * bcm281xx architecture clock framework
10989ce049SDarwin Rambo  *
11989ce049SDarwin Rambo  */
12989ce049SDarwin Rambo 
13989ce049SDarwin Rambo #include <common.h>
14989ce049SDarwin Rambo #include <asm/io.h>
151221ce45SMasahiro Yamada #include <linux/errno.h>
16989ce049SDarwin Rambo #include <bitfield.h>
17989ce049SDarwin Rambo #include <asm/arch/sysmap.h>
18989ce049SDarwin Rambo #include <asm/kona-common/clk.h>
19989ce049SDarwin Rambo #include "clk-core.h"
20989ce049SDarwin Rambo 
21989ce049SDarwin Rambo #define CLK_WR_ACCESS_PASSWORD	0x00a5a501
22989ce049SDarwin Rambo #define WR_ACCESS_OFFSET	0	/* common to all clock blocks */
23989ce049SDarwin Rambo #define POLICY_CTL_GO		1	/* Load and refresh policy masks */
24989ce049SDarwin Rambo #define POLICY_CTL_GO_ATL	4	/* Active Load */
25989ce049SDarwin Rambo 
26989ce049SDarwin Rambo /* Helper function */
clk_get_and_enable(char * clkstr)27989ce049SDarwin Rambo int clk_get_and_enable(char *clkstr)
28989ce049SDarwin Rambo {
29989ce049SDarwin Rambo 	int ret = 0;
30989ce049SDarwin Rambo 	struct clk *c;
31989ce049SDarwin Rambo 
32989ce049SDarwin Rambo 	debug("%s: %s\n", __func__, clkstr);
33989ce049SDarwin Rambo 
34989ce049SDarwin Rambo 	c = clk_get(clkstr);
35989ce049SDarwin Rambo 	if (c) {
36989ce049SDarwin Rambo 		ret = clk_enable(c);
37989ce049SDarwin Rambo 		if (ret)
38989ce049SDarwin Rambo 			return ret;
39989ce049SDarwin Rambo 	} else {
40989ce049SDarwin Rambo 		printf("%s: Couldn't find %s\n", __func__, clkstr);
41989ce049SDarwin Rambo 		return -EINVAL;
42989ce049SDarwin Rambo 	}
43989ce049SDarwin Rambo 	return ret;
44989ce049SDarwin Rambo }
45989ce049SDarwin Rambo 
46989ce049SDarwin Rambo /*
47989ce049SDarwin Rambo  * Poll a register in a CCU's address space, returning when the
48989ce049SDarwin Rambo  * specified bit in that register's value is set (or clear).  Delay
49989ce049SDarwin Rambo  * a microsecond after each read of the register.  Returns true if
50989ce049SDarwin Rambo  * successful, or false if we gave up trying.
51989ce049SDarwin Rambo  *
52989ce049SDarwin Rambo  * Caller must ensure the CCU lock is held.
53989ce049SDarwin Rambo  */
54989ce049SDarwin Rambo #define CLK_GATE_DELAY_USEC 2000
wait_bit(void * base,u32 offset,u32 bit,bool want)55989ce049SDarwin Rambo static inline int wait_bit(void *base, u32 offset, u32 bit, bool want)
56989ce049SDarwin Rambo {
57989ce049SDarwin Rambo 	unsigned int tries;
58989ce049SDarwin Rambo 	u32 bit_mask = 1 << bit;
59989ce049SDarwin Rambo 
60989ce049SDarwin Rambo 	for (tries = 0; tries < CLK_GATE_DELAY_USEC; tries++) {
61989ce049SDarwin Rambo 		u32 val;
62989ce049SDarwin Rambo 		bool bit_val;
63989ce049SDarwin Rambo 
64989ce049SDarwin Rambo 		val = readl(base + offset);
65989ce049SDarwin Rambo 		bit_val = (val & bit_mask) ? 1 : 0;
66989ce049SDarwin Rambo 		if (bit_val == want)
67989ce049SDarwin Rambo 			return 0;	/* success */
68989ce049SDarwin Rambo 		udelay(1);
69989ce049SDarwin Rambo 	}
70989ce049SDarwin Rambo 
71989ce049SDarwin Rambo 	debug("%s: timeout on addr 0x%p, waiting for bit %d to go to %d\n",
72989ce049SDarwin Rambo 	      __func__, base + offset, bit, want);
73989ce049SDarwin Rambo 
74989ce049SDarwin Rambo 	return -ETIMEDOUT;
75989ce049SDarwin Rambo }
76989ce049SDarwin Rambo 
77989ce049SDarwin Rambo /* Enable a peripheral clock */
peri_clk_enable(struct clk * c,int enable)78989ce049SDarwin Rambo static int peri_clk_enable(struct clk *c, int enable)
79989ce049SDarwin Rambo {
80989ce049SDarwin Rambo 	int ret = 0;
81989ce049SDarwin Rambo 	u32 reg;
82989ce049SDarwin Rambo 	struct peri_clock *peri_clk = to_peri_clk(c);
83989ce049SDarwin Rambo 	struct peri_clk_data *cd = peri_clk->data;
84989ce049SDarwin Rambo 	struct bcm_clk_gate *gate = &cd->gate;
85989ce049SDarwin Rambo 	void *base = (void *)c->ccu_clk_mgr_base;
86989ce049SDarwin Rambo 
87989ce049SDarwin Rambo 
88989ce049SDarwin Rambo 	debug("%s: %s\n", __func__, c->name);
89989ce049SDarwin Rambo 
90989ce049SDarwin Rambo 	clk_get_rate(c);	/* Make sure rate and sel are filled in */
91989ce049SDarwin Rambo 
92989ce049SDarwin Rambo 	/* enable access */
93989ce049SDarwin Rambo 	writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
94989ce049SDarwin Rambo 
95989ce049SDarwin Rambo 	if (enable) {
96989ce049SDarwin Rambo 		debug("%s %s set rate %lu div %lu sel %d parent %lu\n",
97989ce049SDarwin Rambo 		      __func__, c->name, c->rate, c->div, c->sel,
98989ce049SDarwin Rambo 		      c->parent->rate);
99989ce049SDarwin Rambo 
100989ce049SDarwin Rambo 		/*
101989ce049SDarwin Rambo 		 * clkgate - only software controllable gates are
102989ce049SDarwin Rambo 		 * supported by u-boot which includes all clocks
103989ce049SDarwin Rambo 		 * that matter. This avoids bringing in a lot of extra
104989ce049SDarwin Rambo 		 * complexity as done in the kernel framework.
105989ce049SDarwin Rambo 		 */
106989ce049SDarwin Rambo 		if (gate_exists(gate)) {
107989ce049SDarwin Rambo 			reg = readl(base + cd->gate.offset);
108989ce049SDarwin Rambo 			reg |= (1 << cd->gate.en_bit);
109989ce049SDarwin Rambo 			writel(reg, base + cd->gate.offset);
110989ce049SDarwin Rambo 		}
111989ce049SDarwin Rambo 
112989ce049SDarwin Rambo 		/* div and pll select */
113989ce049SDarwin Rambo 		if (divider_exists(&cd->div)) {
114989ce049SDarwin Rambo 			reg = readl(base + cd->div.offset);
115989ce049SDarwin Rambo 			bitfield_replace(reg, cd->div.shift, cd->div.width,
116989ce049SDarwin Rambo 					 c->div - 1);
117989ce049SDarwin Rambo 			writel(reg, base + cd->div.offset);
118989ce049SDarwin Rambo 		}
119989ce049SDarwin Rambo 
120989ce049SDarwin Rambo 		/* frequency selector */
121989ce049SDarwin Rambo 		if (selector_exists(&cd->sel)) {
122989ce049SDarwin Rambo 			reg = readl(base + cd->sel.offset);
123989ce049SDarwin Rambo 			bitfield_replace(reg, cd->sel.shift, cd->sel.width,
124989ce049SDarwin Rambo 					 c->sel);
125989ce049SDarwin Rambo 			writel(reg, base + cd->sel.offset);
126989ce049SDarwin Rambo 		}
127989ce049SDarwin Rambo 
128989ce049SDarwin Rambo 		/* trigger */
129989ce049SDarwin Rambo 		if (trigger_exists(&cd->trig)) {
130989ce049SDarwin Rambo 			writel((1 << cd->trig.bit), base + cd->trig.offset);
131989ce049SDarwin Rambo 
132989ce049SDarwin Rambo 			/* wait for trigger status bit to go to 0 */
133989ce049SDarwin Rambo 			ret = wait_bit(base, cd->trig.offset, cd->trig.bit, 0);
134989ce049SDarwin Rambo 			if (ret)
135989ce049SDarwin Rambo 				return ret;
136989ce049SDarwin Rambo 		}
137989ce049SDarwin Rambo 
138989ce049SDarwin Rambo 		/* wait for running (status_bit = 1) */
139989ce049SDarwin Rambo 		ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 1);
140989ce049SDarwin Rambo 		if (ret)
141989ce049SDarwin Rambo 			return ret;
142989ce049SDarwin Rambo 	} else {
143989ce049SDarwin Rambo 		debug("%s disable clock %s\n", __func__, c->name);
144989ce049SDarwin Rambo 
145989ce049SDarwin Rambo 		/* clkgate */
146989ce049SDarwin Rambo 		reg = readl(base + cd->gate.offset);
147989ce049SDarwin Rambo 		reg &= ~(1 << cd->gate.en_bit);
148989ce049SDarwin Rambo 		writel(reg, base + cd->gate.offset);
149989ce049SDarwin Rambo 
150989ce049SDarwin Rambo 		/* wait for stop (status_bit = 0) */
151989ce049SDarwin Rambo 		ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 0);
152989ce049SDarwin Rambo 	}
153989ce049SDarwin Rambo 
154989ce049SDarwin Rambo 	/* disable access */
155989ce049SDarwin Rambo 	writel(0, base + WR_ACCESS_OFFSET);
156989ce049SDarwin Rambo 
157989ce049SDarwin Rambo 	return ret;
158989ce049SDarwin Rambo }
159989ce049SDarwin Rambo 
160989ce049SDarwin Rambo /* Set the rate of a peripheral clock */
peri_clk_set_rate(struct clk * c,unsigned long rate)161989ce049SDarwin Rambo static int peri_clk_set_rate(struct clk *c, unsigned long rate)
162989ce049SDarwin Rambo {
163989ce049SDarwin Rambo 	int ret = 0;
164989ce049SDarwin Rambo 	int i;
165989ce049SDarwin Rambo 	unsigned long diff;
166989ce049SDarwin Rambo 	unsigned long new_rate = 0, div = 1;
167989ce049SDarwin Rambo 	struct peri_clock *peri_clk = to_peri_clk(c);
168989ce049SDarwin Rambo 	struct peri_clk_data *cd = peri_clk->data;
169989ce049SDarwin Rambo 	const char **clock;
170989ce049SDarwin Rambo 
171989ce049SDarwin Rambo 	debug("%s: %s\n", __func__, c->name);
172989ce049SDarwin Rambo 	diff = rate;
173989ce049SDarwin Rambo 
174989ce049SDarwin Rambo 	i = 0;
175989ce049SDarwin Rambo 	for (clock = cd->clocks; *clock; clock++, i++) {
176989ce049SDarwin Rambo 		struct refclk *ref = refclk_str_to_clk(*clock);
177989ce049SDarwin Rambo 		if (!ref) {
178989ce049SDarwin Rambo 			printf("%s: Lookup of %s failed\n", __func__, *clock);
179989ce049SDarwin Rambo 			return -EINVAL;
180989ce049SDarwin Rambo 		}
181989ce049SDarwin Rambo 
182989ce049SDarwin Rambo 		/* round to the new rate */
183989ce049SDarwin Rambo 		div = ref->clk.rate / rate;
184989ce049SDarwin Rambo 		if (div == 0)
185989ce049SDarwin Rambo 			div = 1;
186989ce049SDarwin Rambo 
187989ce049SDarwin Rambo 		new_rate = ref->clk.rate / div;
188989ce049SDarwin Rambo 
189989ce049SDarwin Rambo 		/* get the min diff */
190989ce049SDarwin Rambo 		if (abs(new_rate - rate) < diff) {
191989ce049SDarwin Rambo 			diff = abs(new_rate - rate);
192989ce049SDarwin Rambo 			c->sel = i;
193989ce049SDarwin Rambo 			c->parent = &ref->clk;
194989ce049SDarwin Rambo 			c->rate = new_rate;
195989ce049SDarwin Rambo 			c->div = div;
196989ce049SDarwin Rambo 		}
197989ce049SDarwin Rambo 	}
198989ce049SDarwin Rambo 
199989ce049SDarwin Rambo 	debug("%s %s set rate %lu div %lu sel %d parent %lu\n", __func__,
200989ce049SDarwin Rambo 	      c->name, c->rate, c->div, c->sel, c->parent->rate);
201989ce049SDarwin Rambo 	return ret;
202989ce049SDarwin Rambo }
203989ce049SDarwin Rambo 
204989ce049SDarwin Rambo /* Get the rate of a peripheral clock */
peri_clk_get_rate(struct clk * c)205989ce049SDarwin Rambo static unsigned long peri_clk_get_rate(struct clk *c)
206989ce049SDarwin Rambo {
207989ce049SDarwin Rambo 	struct peri_clock *peri_clk = to_peri_clk(c);
208989ce049SDarwin Rambo 	struct peri_clk_data *cd = peri_clk->data;
209989ce049SDarwin Rambo 	void *base = (void *)c->ccu_clk_mgr_base;
210989ce049SDarwin Rambo 	int div = 1;
211989ce049SDarwin Rambo 	const char **clock;
212989ce049SDarwin Rambo 	struct refclk *ref;
213989ce049SDarwin Rambo 	u32 reg;
214989ce049SDarwin Rambo 
215989ce049SDarwin Rambo 	debug("%s: %s\n", __func__, c->name);
216989ce049SDarwin Rambo 	if (selector_exists(&cd->sel)) {
217989ce049SDarwin Rambo 		reg = readl(base + cd->sel.offset);
218989ce049SDarwin Rambo 		c->sel = bitfield_extract(reg, cd->sel.shift, cd->sel.width);
219989ce049SDarwin Rambo 	} else {
220989ce049SDarwin Rambo 		/*
221989ce049SDarwin Rambo 		 * For peri clocks that don't have a selector, the single
222989ce049SDarwin Rambo 		 * reference clock will always exist at index 0.
223989ce049SDarwin Rambo 		 */
224989ce049SDarwin Rambo 		c->sel = 0;
225989ce049SDarwin Rambo 	}
226989ce049SDarwin Rambo 
227989ce049SDarwin Rambo 	if (divider_exists(&cd->div)) {
228989ce049SDarwin Rambo 		reg = readl(base + cd->div.offset);
229989ce049SDarwin Rambo 		div = bitfield_extract(reg, cd->div.shift, cd->div.width);
230989ce049SDarwin Rambo 		div += 1;
231989ce049SDarwin Rambo 	}
232989ce049SDarwin Rambo 
233989ce049SDarwin Rambo 	clock = cd->clocks;
234989ce049SDarwin Rambo 	ref = refclk_str_to_clk(clock[c->sel]);
235989ce049SDarwin Rambo 	if (!ref) {
236989ce049SDarwin Rambo 		printf("%s: Can't lookup %s\n", __func__, clock[c->sel]);
237989ce049SDarwin Rambo 		return 0;
238989ce049SDarwin Rambo 	}
239989ce049SDarwin Rambo 
240989ce049SDarwin Rambo 	c->parent = &ref->clk;
241989ce049SDarwin Rambo 	c->div = div;
242989ce049SDarwin Rambo 	c->rate = c->parent->rate / c->div;
243989ce049SDarwin Rambo 	debug("%s parent rate %lu div %d sel %d rate %lu\n", __func__,
244989ce049SDarwin Rambo 	      c->parent->rate, div, c->sel, c->rate);
245989ce049SDarwin Rambo 
246989ce049SDarwin Rambo 	return c->rate;
247989ce049SDarwin Rambo }
248989ce049SDarwin Rambo 
249989ce049SDarwin Rambo /* Peripheral clock operations */
250989ce049SDarwin Rambo struct clk_ops peri_clk_ops = {
251989ce049SDarwin Rambo 	.enable = peri_clk_enable,
252989ce049SDarwin Rambo 	.set_rate = peri_clk_set_rate,
253989ce049SDarwin Rambo 	.get_rate = peri_clk_get_rate,
254989ce049SDarwin Rambo };
255989ce049SDarwin Rambo 
256989ce049SDarwin Rambo /* Enable a CCU clock */
ccu_clk_enable(struct clk * c,int enable)257989ce049SDarwin Rambo static int ccu_clk_enable(struct clk *c, int enable)
258989ce049SDarwin Rambo {
259989ce049SDarwin Rambo 	struct ccu_clock *ccu_clk = to_ccu_clk(c);
260989ce049SDarwin Rambo 	void *base = (void *)c->ccu_clk_mgr_base;
261989ce049SDarwin Rambo 	int ret = 0;
262989ce049SDarwin Rambo 	u32 reg;
263989ce049SDarwin Rambo 
264989ce049SDarwin Rambo 	debug("%s: %s\n", __func__, c->name);
265989ce049SDarwin Rambo 	if (!enable)
266989ce049SDarwin Rambo 		return -EINVAL;	/* CCU clock cannot shutdown */
267989ce049SDarwin Rambo 
268989ce049SDarwin Rambo 	/* enable access */
269989ce049SDarwin Rambo 	writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
270989ce049SDarwin Rambo 
271989ce049SDarwin Rambo 	/* config enable for policy engine */
272989ce049SDarwin Rambo 	writel(1, base + ccu_clk->lvm_en_offset);
273989ce049SDarwin Rambo 
274989ce049SDarwin Rambo 	/* wait for bit to go to 0 */
275989ce049SDarwin Rambo 	ret = wait_bit(base, ccu_clk->lvm_en_offset, 0, 0);
276989ce049SDarwin Rambo 	if (ret)
277989ce049SDarwin Rambo 		return ret;
278989ce049SDarwin Rambo 
279989ce049SDarwin Rambo 	/* freq ID */
280989ce049SDarwin Rambo 	if (!ccu_clk->freq_bit_shift)
281989ce049SDarwin Rambo 		ccu_clk->freq_bit_shift = 8;
282989ce049SDarwin Rambo 
283989ce049SDarwin Rambo 	/* Set frequency id for each of the 4 policies */
284989ce049SDarwin Rambo 	reg = ccu_clk->freq_id |
285989ce049SDarwin Rambo 	    (ccu_clk->freq_id << (ccu_clk->freq_bit_shift)) |
286989ce049SDarwin Rambo 	    (ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 2)) |
287989ce049SDarwin Rambo 	    (ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 3));
288989ce049SDarwin Rambo 	writel(reg, base + ccu_clk->policy_freq_offset);
289989ce049SDarwin Rambo 
290989ce049SDarwin Rambo 	/* enable all clock mask */
291989ce049SDarwin Rambo 	writel(0x7fffffff, base + ccu_clk->policy0_mask_offset);
292989ce049SDarwin Rambo 	writel(0x7fffffff, base + ccu_clk->policy1_mask_offset);
293989ce049SDarwin Rambo 	writel(0x7fffffff, base + ccu_clk->policy2_mask_offset);
294989ce049SDarwin Rambo 	writel(0x7fffffff, base + ccu_clk->policy3_mask_offset);
295989ce049SDarwin Rambo 
296989ce049SDarwin Rambo 	if (ccu_clk->num_policy_masks == 2) {
297989ce049SDarwin Rambo 		writel(0x7fffffff, base + ccu_clk->policy0_mask2_offset);
298989ce049SDarwin Rambo 		writel(0x7fffffff, base + ccu_clk->policy1_mask2_offset);
299989ce049SDarwin Rambo 		writel(0x7fffffff, base + ccu_clk->policy2_mask2_offset);
300989ce049SDarwin Rambo 		writel(0x7fffffff, base + ccu_clk->policy3_mask2_offset);
301989ce049SDarwin Rambo 	}
302989ce049SDarwin Rambo 
303989ce049SDarwin Rambo 	/* start policy engine */
304989ce049SDarwin Rambo 	reg = readl(base + ccu_clk->policy_ctl_offset);
305989ce049SDarwin Rambo 	reg |= (POLICY_CTL_GO + POLICY_CTL_GO_ATL);
306989ce049SDarwin Rambo 	writel(reg, base + ccu_clk->policy_ctl_offset);
307989ce049SDarwin Rambo 
308989ce049SDarwin Rambo 	/* wait till started */
309989ce049SDarwin Rambo 	ret = wait_bit(base, ccu_clk->policy_ctl_offset, 0, 0);
310989ce049SDarwin Rambo 	if (ret)
311989ce049SDarwin Rambo 		return ret;
312989ce049SDarwin Rambo 
313989ce049SDarwin Rambo 	/* disable access */
314989ce049SDarwin Rambo 	writel(0, base + WR_ACCESS_OFFSET);
315989ce049SDarwin Rambo 
316989ce049SDarwin Rambo 	return ret;
317989ce049SDarwin Rambo }
318989ce049SDarwin Rambo 
319989ce049SDarwin Rambo /* Get the CCU clock rate */
ccu_clk_get_rate(struct clk * c)320989ce049SDarwin Rambo static unsigned long ccu_clk_get_rate(struct clk *c)
321989ce049SDarwin Rambo {
322989ce049SDarwin Rambo 	struct ccu_clock *ccu_clk = to_ccu_clk(c);
323989ce049SDarwin Rambo 	debug("%s: %s\n", __func__, c->name);
324989ce049SDarwin Rambo 	c->rate = ccu_clk->freq_tbl[ccu_clk->freq_id];
325989ce049SDarwin Rambo 	return c->rate;
326989ce049SDarwin Rambo }
327989ce049SDarwin Rambo 
328989ce049SDarwin Rambo /* CCU clock operations */
329989ce049SDarwin Rambo struct clk_ops ccu_clk_ops = {
330989ce049SDarwin Rambo 	.enable = ccu_clk_enable,
331989ce049SDarwin Rambo 	.get_rate = ccu_clk_get_rate,
332989ce049SDarwin Rambo };
333989ce049SDarwin Rambo 
334989ce049SDarwin Rambo /* Enable a bus clock */
bus_clk_enable(struct clk * c,int enable)335989ce049SDarwin Rambo static int bus_clk_enable(struct clk *c, int enable)
336989ce049SDarwin Rambo {
337989ce049SDarwin Rambo 	struct bus_clock *bus_clk = to_bus_clk(c);
338989ce049SDarwin Rambo 	struct bus_clk_data *cd = bus_clk->data;
339989ce049SDarwin Rambo 	void *base = (void *)c->ccu_clk_mgr_base;
340989ce049SDarwin Rambo 	int ret = 0;
341989ce049SDarwin Rambo 	u32 reg;
342989ce049SDarwin Rambo 
343989ce049SDarwin Rambo 	debug("%s: %s\n", __func__, c->name);
344989ce049SDarwin Rambo 	/* enable access */
345989ce049SDarwin Rambo 	writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
346989ce049SDarwin Rambo 
347989ce049SDarwin Rambo 	/* enable gating */
348989ce049SDarwin Rambo 	reg = readl(base + cd->gate.offset);
349989ce049SDarwin Rambo 	if (!!(reg & (1 << cd->gate.status_bit)) == !!enable)
350989ce049SDarwin Rambo 		debug("%s already %s\n", c->name,
351989ce049SDarwin Rambo 		      enable ? "enabled" : "disabled");
352989ce049SDarwin Rambo 	else {
353989ce049SDarwin Rambo 		int want = (enable) ? 1 : 0;
354989ce049SDarwin Rambo 		reg |= (1 << cd->gate.hw_sw_sel_bit);
355989ce049SDarwin Rambo 
356989ce049SDarwin Rambo 		if (enable)
357989ce049SDarwin Rambo 			reg |= (1 << cd->gate.en_bit);
358989ce049SDarwin Rambo 		else
359989ce049SDarwin Rambo 			reg &= ~(1 << cd->gate.en_bit);
360989ce049SDarwin Rambo 
361989ce049SDarwin Rambo 		writel(reg, base + cd->gate.offset);
362989ce049SDarwin Rambo 		ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit,
363989ce049SDarwin Rambo 			       want);
364989ce049SDarwin Rambo 		if (ret)
365989ce049SDarwin Rambo 			return ret;
366989ce049SDarwin Rambo 	}
367989ce049SDarwin Rambo 
368989ce049SDarwin Rambo 	/* disable access */
369989ce049SDarwin Rambo 	writel(0, base + WR_ACCESS_OFFSET);
370989ce049SDarwin Rambo 
371989ce049SDarwin Rambo 	return ret;
372989ce049SDarwin Rambo }
373989ce049SDarwin Rambo 
374989ce049SDarwin Rambo /* Get the rate of a bus clock */
bus_clk_get_rate(struct clk * c)375989ce049SDarwin Rambo static unsigned long bus_clk_get_rate(struct clk *c)
376989ce049SDarwin Rambo {
377989ce049SDarwin Rambo 	struct bus_clock *bus_clk = to_bus_clk(c);
378989ce049SDarwin Rambo 	struct ccu_clock *ccu_clk;
379989ce049SDarwin Rambo 
380989ce049SDarwin Rambo 	debug("%s: %s\n", __func__, c->name);
381989ce049SDarwin Rambo 	ccu_clk = to_ccu_clk(c->parent);
382989ce049SDarwin Rambo 
383989ce049SDarwin Rambo 	c->rate = bus_clk->freq_tbl[ccu_clk->freq_id];
384989ce049SDarwin Rambo 	c->div = ccu_clk->freq_tbl[ccu_clk->freq_id] / c->rate;
385989ce049SDarwin Rambo 	return c->rate;
386989ce049SDarwin Rambo }
387989ce049SDarwin Rambo 
388989ce049SDarwin Rambo /* Bus clock operations */
389989ce049SDarwin Rambo struct clk_ops bus_clk_ops = {
390989ce049SDarwin Rambo 	.enable = bus_clk_enable,
391989ce049SDarwin Rambo 	.get_rate = bus_clk_get_rate,
392989ce049SDarwin Rambo };
393989ce049SDarwin Rambo 
394989ce049SDarwin Rambo /* Enable a reference clock */
ref_clk_enable(struct clk * c,int enable)395989ce049SDarwin Rambo static int ref_clk_enable(struct clk *c, int enable)
396989ce049SDarwin Rambo {
397989ce049SDarwin Rambo 	debug("%s: %s\n", __func__, c->name);
398989ce049SDarwin Rambo 	return 0;
399989ce049SDarwin Rambo }
400989ce049SDarwin Rambo 
401989ce049SDarwin Rambo /* Reference clock operations */
402989ce049SDarwin Rambo struct clk_ops ref_clk_ops = {
403989ce049SDarwin Rambo 	.enable = ref_clk_enable,
404989ce049SDarwin Rambo };
405989ce049SDarwin Rambo 
406989ce049SDarwin Rambo /*
407989ce049SDarwin Rambo  * clk.h implementation follows
408989ce049SDarwin Rambo  */
409989ce049SDarwin Rambo 
410989ce049SDarwin Rambo /* Initialize the clock framework */
clk_init(void)411989ce049SDarwin Rambo int clk_init(void)
412989ce049SDarwin Rambo {
413989ce049SDarwin Rambo 	debug("%s:\n", __func__);
414989ce049SDarwin Rambo 	return 0;
415989ce049SDarwin Rambo }
416989ce049SDarwin Rambo 
417989ce049SDarwin Rambo /* Get a clock handle, give a name string */
clk_get(const char * con_id)418989ce049SDarwin Rambo struct clk *clk_get(const char *con_id)
419989ce049SDarwin Rambo {
420989ce049SDarwin Rambo 	int i;
421989ce049SDarwin Rambo 	struct clk_lookup *clk_tblp;
422989ce049SDarwin Rambo 
423989ce049SDarwin Rambo 	debug("%s: %s\n", __func__, con_id);
424989ce049SDarwin Rambo 
425989ce049SDarwin Rambo 	clk_tblp = arch_clk_tbl;
426989ce049SDarwin Rambo 	for (i = 0; i < arch_clk_tbl_array_size; i++, clk_tblp++) {
427989ce049SDarwin Rambo 		if (clk_tblp->con_id) {
428989ce049SDarwin Rambo 			if (!con_id || strcmp(clk_tblp->con_id, con_id))
429989ce049SDarwin Rambo 				continue;
430989ce049SDarwin Rambo 			return clk_tblp->clk;
431989ce049SDarwin Rambo 		}
432989ce049SDarwin Rambo 	}
433989ce049SDarwin Rambo 	return NULL;
434989ce049SDarwin Rambo }
435989ce049SDarwin Rambo 
436989ce049SDarwin Rambo /* Enable a clock */
clk_enable(struct clk * c)437989ce049SDarwin Rambo int clk_enable(struct clk *c)
438989ce049SDarwin Rambo {
439989ce049SDarwin Rambo 	int ret = 0;
440989ce049SDarwin Rambo 
441989ce049SDarwin Rambo 	debug("%s: %s\n", __func__, c->name);
442989ce049SDarwin Rambo 	if (!c->ops || !c->ops->enable)
443989ce049SDarwin Rambo 		return -1;
444989ce049SDarwin Rambo 
445989ce049SDarwin Rambo 	/* enable parent clock first */
446989ce049SDarwin Rambo 	if (c->parent)
447989ce049SDarwin Rambo 		ret = clk_enable(c->parent);
448989ce049SDarwin Rambo 
449989ce049SDarwin Rambo 	if (ret)
450989ce049SDarwin Rambo 		return ret;
451989ce049SDarwin Rambo 
452989ce049SDarwin Rambo 	if (!c->use_cnt) {
453989ce049SDarwin Rambo 		c->use_cnt++;
454989ce049SDarwin Rambo 		ret = c->ops->enable(c, 1);
455989ce049SDarwin Rambo 	}
456989ce049SDarwin Rambo 
457989ce049SDarwin Rambo 	return ret;
458989ce049SDarwin Rambo }
459989ce049SDarwin Rambo 
460989ce049SDarwin Rambo /* Disable a clock */
clk_disable(struct clk * c)461989ce049SDarwin Rambo void clk_disable(struct clk *c)
462989ce049SDarwin Rambo {
463989ce049SDarwin Rambo 	debug("%s: %s\n", __func__, c->name);
464989ce049SDarwin Rambo 	if (!c->ops || !c->ops->enable)
465989ce049SDarwin Rambo 		return;
466989ce049SDarwin Rambo 
467989ce049SDarwin Rambo 	if (c->use_cnt) {
468989ce049SDarwin Rambo 		c->use_cnt--;
469989ce049SDarwin Rambo 		c->ops->enable(c, 0);
470989ce049SDarwin Rambo 	}
471989ce049SDarwin Rambo 
472989ce049SDarwin Rambo 	/* disable parent */
473989ce049SDarwin Rambo 	if (c->parent)
474989ce049SDarwin Rambo 		clk_disable(c->parent);
475989ce049SDarwin Rambo }
476989ce049SDarwin Rambo 
477989ce049SDarwin Rambo /* Get the clock rate */
clk_get_rate(struct clk * c)478989ce049SDarwin Rambo unsigned long clk_get_rate(struct clk *c)
479989ce049SDarwin Rambo {
480989ce049SDarwin Rambo 	unsigned long rate;
481989ce049SDarwin Rambo 
482989ce049SDarwin Rambo 	if (!c || !c->ops || !c->ops->get_rate)
483989ce049SDarwin Rambo 		return 0;
484*6def7de3Sxypron.glpk@gmx.de 	debug("%s: %s\n", __func__, c->name);
485989ce049SDarwin Rambo 
486989ce049SDarwin Rambo 	rate = c->ops->get_rate(c);
487989ce049SDarwin Rambo 	debug("%s: rate = %ld\n", __func__, rate);
488989ce049SDarwin Rambo 	return rate;
489989ce049SDarwin Rambo }
490989ce049SDarwin Rambo 
491989ce049SDarwin Rambo /* Set the clock rate */
clk_set_rate(struct clk * c,unsigned long rate)492989ce049SDarwin Rambo int clk_set_rate(struct clk *c, unsigned long rate)
493989ce049SDarwin Rambo {
494989ce049SDarwin Rambo 	int ret;
495989ce049SDarwin Rambo 
496989ce049SDarwin Rambo 	if (!c || !c->ops || !c->ops->set_rate)
497989ce049SDarwin Rambo 		return -EINVAL;
498*6def7de3Sxypron.glpk@gmx.de 	debug("%s: %s rate=%ld\n", __func__, c->name, rate);
499989ce049SDarwin Rambo 
500989ce049SDarwin Rambo 	if (c->use_cnt)
501989ce049SDarwin Rambo 		return -EINVAL;
502989ce049SDarwin Rambo 
503989ce049SDarwin Rambo 	ret = c->ops->set_rate(c, rate);
504989ce049SDarwin Rambo 
505989ce049SDarwin Rambo 	return ret;
506989ce049SDarwin Rambo }
507989ce049SDarwin Rambo 
508989ce049SDarwin Rambo /* Not required for this arch */
509989ce049SDarwin Rambo /*
510989ce049SDarwin Rambo long clk_round_rate(struct clk *clk, unsigned long rate);
511989ce049SDarwin Rambo int clk_set_parent(struct clk *clk, struct clk *parent);
512989ce049SDarwin Rambo struct clk *clk_get_parent(struct clk *clk);
513989ce049SDarwin Rambo */
514