1/*
2 * R8A7740 processor support
3 *
4 * Copyright (C) 2011  Renesas Solutions Corp.
5 * Copyright (C) 2011  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 */
16#include <linux/init.h>
17#include <linux/kernel.h>
18#include <linux/io.h>
19#include <linux/sh_clk.h>
20#include <linux/clkdev.h>
21
22#include "clock.h"
23#include "common.h"
24#include "r8a7740.h"
25
26/*
27 *        |  MDx  |  XTAL1/EXTAL1   |  System   | EXTALR |
28 *  Clock |-------+-----------------+  clock    | 32.768 |   RCLK
29 *  Mode  | 2/1/0 | src         MHz |  source   |  KHz   |  source
30 * -------+-------+-----------------+-----------+--------+----------
31 *    0   | 0 0 0 | External  20~50 | XTAL1     |    O   |  EXTALR
32 *    1   | 0 0 1 | Crystal   20~30 | XTAL1     |    O   |  EXTALR
33 *    2   | 0 1 0 | External  40~50 | XTAL1 / 2 |    O   |  EXTALR
34 *    3   | 0 1 1 | Crystal   40~50 | XTAL1 / 2 |    O   |  EXTALR
35 *    4   | 1 0 0 | External  20~50 | XTAL1     |    x   |  XTAL1 / 1024
36 *    5   | 1 0 1 | Crystal   20~30 | XTAL1     |    x   |  XTAL1 / 1024
37 *    6   | 1 1 0 | External  40~50 | XTAL1 / 2 |    x   |  XTAL1 / 2048
38 *    7   | 1 1 1 | Crystal   40~50 | XTAL1 / 2 |    x   |  XTAL1 / 2048
39 */
40
41/* CPG registers */
42#define FRQCRA		IOMEM(0xe6150000)
43#define FRQCRB		IOMEM(0xe6150004)
44#define VCLKCR1		IOMEM(0xE6150008)
45#define VCLKCR2		IOMEM(0xE615000c)
46#define FRQCRC		IOMEM(0xe61500e0)
47#define FSIACKCR	IOMEM(0xe6150018)
48#define PLLC01CR	IOMEM(0xe6150028)
49
50#define SUBCKCR		IOMEM(0xe6150080)
51#define USBCKCR		IOMEM(0xe615008c)
52
53#define MSTPSR0		IOMEM(0xe6150030)
54#define MSTPSR1		IOMEM(0xe6150038)
55#define MSTPSR2		IOMEM(0xe6150040)
56#define MSTPSR3		IOMEM(0xe6150048)
57#define MSTPSR4		IOMEM(0xe615004c)
58#define FSIBCKCR	IOMEM(0xe6150090)
59#define HDMICKCR	IOMEM(0xe6150094)
60#define SMSTPCR0	IOMEM(0xe6150130)
61#define SMSTPCR1	IOMEM(0xe6150134)
62#define SMSTPCR2	IOMEM(0xe6150138)
63#define SMSTPCR3	IOMEM(0xe615013c)
64#define SMSTPCR4	IOMEM(0xe6150140)
65
66#define FSIDIVA		IOMEM(0xFE1F8000)
67#define FSIDIVB		IOMEM(0xFE1F8008)
68
69/* Fixed 32 KHz root clock from EXTALR pin */
70static struct clk extalr_clk = {
71	.rate	= 32768,
72};
73
74/*
75 * 25MHz default rate for the EXTAL1 root input clock.
76 * If needed, reset this with clk_set_rate() from the platform code.
77 */
78static struct clk extal1_clk = {
79	.rate	= 25000000,
80};
81
82/*
83 * 48MHz default rate for the EXTAL2 root input clock.
84 * If needed, reset this with clk_set_rate() from the platform code.
85 */
86static struct clk extal2_clk = {
87	.rate	= 48000000,
88};
89
90/*
91 * 27MHz default rate for the DV_CLKI root input clock.
92 * If needed, reset this with clk_set_rate() from the platform code.
93 */
94static struct clk dv_clk = {
95	.rate	= 27000000,
96};
97
98SH_CLK_RATIO(div2,	1, 2);
99SH_CLK_RATIO(div1k,	1, 1024);
100
101SH_FIXED_RATIO_CLK(extal1_div2_clk,	extal1_clk,		div2);
102SH_FIXED_RATIO_CLK(extal1_div1024_clk,	extal1_clk,		div1k);
103SH_FIXED_RATIO_CLK(extal1_div2048_clk,	extal1_div2_clk,	div1k);
104SH_FIXED_RATIO_CLK(extal2_div2_clk,	extal2_clk,		div2);
105
106static struct sh_clk_ops followparent_clk_ops = {
107	.recalc	= followparent_recalc,
108};
109
110/* Main clock */
111static struct clk system_clk = {
112	.ops	= &followparent_clk_ops,
113};
114
115SH_FIXED_RATIO_CLK(system_div2_clk, system_clk,	div2);
116
117/* r_clk */
118static struct clk r_clk = {
119	.ops	= &followparent_clk_ops,
120};
121
122/* PLLC0/PLLC1 */
123static unsigned long pllc01_recalc(struct clk *clk)
124{
125	unsigned long mult = 1;
126
127	if (__raw_readl(PLLC01CR) & (1 << 14))
128		mult = ((__raw_readl(clk->enable_reg) >> 24) & 0x7f) + 1;
129
130	return clk->parent->rate * mult;
131}
132
133static struct sh_clk_ops pllc01_clk_ops = {
134	.recalc		= pllc01_recalc,
135};
136
137static struct clk pllc0_clk = {
138	.ops		= &pllc01_clk_ops,
139	.flags		= CLK_ENABLE_ON_INIT,
140	.parent		= &system_clk,
141	.enable_reg	= (void __iomem *)FRQCRC,
142};
143
144static struct clk pllc1_clk = {
145	.ops		= &pllc01_clk_ops,
146	.flags		= CLK_ENABLE_ON_INIT,
147	.parent		= &system_div2_clk,
148	.enable_reg	= (void __iomem *)FRQCRA,
149};
150
151/* PLLC1 / 2 */
152SH_FIXED_RATIO_CLK(pllc1_div2_clk, pllc1_clk, div2);
153
154/* USB clock */
155/*
156 * USBCKCR is controlling usb24 clock
157 * bit[7] : parent clock
158 * bit[6] : clock divide rate
159 * And this bit[7] is used as a "usb24s" from other devices.
160 * (Video clock / Sub clock / SPU clock)
161 * You can controll this clock as a below.
162 *
163 * struct clk *usb24	= clk_get(dev,  "usb24");
164 * struct clk *usb24s	= clk_get(NULL, "usb24s");
165 * struct clk *system	= clk_get(NULL, "system_clk");
166 * int rate = clk_get_rate(system);
167 *
168 * clk_set_parent(usb24s, system);  // for bit[7]
169 * clk_set_rate(usb24, rate / 2);   // for bit[6]
170 */
171static struct clk *usb24s_parents[] = {
172	[0] = &system_clk,
173	[1] = &extal2_clk
174};
175
176static int usb24s_enable(struct clk *clk)
177{
178	__raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR);
179
180	return 0;
181}
182
183static void usb24s_disable(struct clk *clk)
184{
185	__raw_writel(__raw_readl(USBCKCR) | (1 << 8), USBCKCR);
186}
187
188static int usb24s_set_parent(struct clk *clk, struct clk *parent)
189{
190	int i, ret;
191	u32 val;
192
193	if (!clk->parent_table || !clk->parent_num)
194		return -EINVAL;
195
196	/* Search the parent */
197	for (i = 0; i < clk->parent_num; i++)
198		if (clk->parent_table[i] == parent)
199			break;
200
201	if (i == clk->parent_num)
202		return -ENODEV;
203
204	ret = clk_reparent(clk, parent);
205	if (ret < 0)
206		return ret;
207
208	val = __raw_readl(USBCKCR);
209	val &= ~(1 << 7);
210	val |= i << 7;
211	__raw_writel(val, USBCKCR);
212
213	return 0;
214}
215
216static struct sh_clk_ops usb24s_clk_ops = {
217	.recalc		= followparent_recalc,
218	.enable		= usb24s_enable,
219	.disable	= usb24s_disable,
220	.set_parent	= usb24s_set_parent,
221};
222
223static struct clk usb24s_clk = {
224	.ops		= &usb24s_clk_ops,
225	.parent_table	= usb24s_parents,
226	.parent_num	= ARRAY_SIZE(usb24s_parents),
227	.parent		= &system_clk,
228};
229
230static unsigned long usb24_recalc(struct clk *clk)
231{
232	return clk->parent->rate /
233		((__raw_readl(USBCKCR) & (1 << 6)) ? 1 : 2);
234};
235
236static int usb24_set_rate(struct clk *clk, unsigned long rate)
237{
238	u32 val;
239
240	/* closer to which ? parent->rate or parent->rate/2 */
241	val = __raw_readl(USBCKCR);
242	val &= ~(1 << 6);
243	val |= (rate > (clk->parent->rate / 4) * 3) << 6;
244	__raw_writel(val, USBCKCR);
245
246	return 0;
247}
248
249static struct sh_clk_ops usb24_clk_ops = {
250	.recalc		= usb24_recalc,
251	.set_rate	= usb24_set_rate,
252};
253
254static struct clk usb24_clk = {
255	.ops		= &usb24_clk_ops,
256	.parent		= &usb24s_clk,
257};
258
259/* External FSIACK/FSIBCK clock */
260static struct clk fsiack_clk = {
261};
262
263static struct clk fsibck_clk = {
264};
265
266static struct clk *main_clks[] = {
267	&extalr_clk,
268	&extal1_clk,
269	&extal2_clk,
270	&extal1_div2_clk,
271	&extal1_div1024_clk,
272	&extal1_div2048_clk,
273	&extal2_div2_clk,
274	&dv_clk,
275	&system_clk,
276	&system_div2_clk,
277	&r_clk,
278	&pllc0_clk,
279	&pllc1_clk,
280	&pllc1_div2_clk,
281	&usb24s_clk,
282	&usb24_clk,
283	&fsiack_clk,
284	&fsibck_clk,
285};
286
287/* DIV4 clocks */
288static void div4_kick(struct clk *clk)
289{
290	unsigned long value;
291
292	/* set KICK bit in FRQCRB to update hardware setting */
293	value = __raw_readl(FRQCRB);
294	value |= (1 << 31);
295	__raw_writel(value, FRQCRB);
296}
297
298static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18,
299			  24, 32, 36, 48, 0, 72, 96, 0 };
300
301static struct clk_div_mult_table div4_div_mult_table = {
302	.divisors = divisors,
303	.nr_divisors = ARRAY_SIZE(divisors),
304};
305
306static struct clk_div4_table div4_table = {
307	.div_mult_table = &div4_div_mult_table,
308	.kick = div4_kick,
309};
310
311enum {
312	DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP,
313	DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP,
314	DIV4_NR
315};
316
317static struct clk div4_clks[DIV4_NR] = {
318	[DIV4_I]	= SH_CLK_DIV4(&pllc1_clk, FRQCRA, 20, 0x6fff, CLK_ENABLE_ON_INIT),
319	[DIV4_ZG]	= SH_CLK_DIV4(&pllc1_clk, FRQCRA, 16, 0x6fff, CLK_ENABLE_ON_INIT),
320	[DIV4_B]	= SH_CLK_DIV4(&pllc1_clk, FRQCRA,  8, 0x6fff, CLK_ENABLE_ON_INIT),
321	[DIV4_M1]	= SH_CLK_DIV4(&pllc1_clk, FRQCRA,  4, 0x6fff, CLK_ENABLE_ON_INIT),
322	[DIV4_HP]	= SH_CLK_DIV4(&pllc1_clk, FRQCRB,  4, 0x6fff, 0),
323	[DIV4_HPP]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0),
324	[DIV4_USBP]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0),
325	[DIV4_S]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0),
326	[DIV4_ZB]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC,  8, 0x6fff, 0),
327	[DIV4_M3]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC,  4, 0x6fff, 0),
328	[DIV4_CP]	= SH_CLK_DIV4(&pllc1_clk, FRQCRC,  0, 0x6fff, 0),
329};
330
331/* DIV6 reparent */
332enum {
333	DIV6_HDMI,
334	DIV6_VCLK1, DIV6_VCLK2,
335	DIV6_FSIA, DIV6_FSIB,
336	DIV6_REPARENT_NR,
337};
338
339static struct clk *hdmi_parent[] = {
340	[0] = &pllc1_div2_clk,
341	[1] = &system_clk,
342	[2] = &dv_clk
343};
344
345static struct clk *vclk_parents[8] = {
346	[0] = &pllc1_div2_clk,
347	[2] = &dv_clk,
348	[3] = &usb24s_clk,
349	[4] = &extal1_div2_clk,
350	[5] = &extalr_clk,
351};
352
353static struct clk *fsia_parents[] = {
354	[0] = &pllc1_div2_clk,
355	[1] = &fsiack_clk, /* external clock */
356};
357
358static struct clk *fsib_parents[] = {
359	[0] = &pllc1_div2_clk,
360	[1] = &fsibck_clk, /* external clock */
361};
362
363static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
364	[DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0,
365				      hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2),
366	[DIV6_VCLK1] = SH_CLK_DIV6_EXT(VCLKCR1, 0,
367				       vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3),
368	[DIV6_VCLK2] = SH_CLK_DIV6_EXT(VCLKCR2, 0,
369				       vclk_parents, ARRAY_SIZE(vclk_parents), 12, 3),
370	[DIV6_FSIA] = SH_CLK_DIV6_EXT(FSIACKCR, 0,
371				      fsia_parents, ARRAY_SIZE(fsia_parents), 6, 2),
372	[DIV6_FSIB] = SH_CLK_DIV6_EXT(FSIBCKCR, 0,
373				      fsib_parents, ARRAY_SIZE(fsib_parents), 6, 2),
374};
375
376/* DIV6 clocks */
377enum {
378	DIV6_SUB,
379	DIV6_NR
380};
381
382static struct clk div6_clks[DIV6_NR] = {
383	[DIV6_SUB]	= SH_CLK_DIV6(&pllc1_div2_clk, SUBCKCR, 0),
384};
385
386/* HDMI1/2 clock */
387static unsigned long hdmi12_recalc(struct clk *clk)
388{
389	u32 val = __raw_readl(HDMICKCR);
390	int shift = (int)clk->priv;
391
392	val >>= shift;
393	val &= 0x3;
394
395	return clk->parent->rate / (1 << val);
396};
397
398static int hdmi12_set_rate(struct clk *clk, unsigned long rate)
399{
400	u32 val, mask;
401	int i, shift;
402
403	for (i = 0; i < 3; i++)
404		if (rate == clk->parent->rate / (1 << i))
405			goto find;
406	return -ENODEV;
407
408find:
409	shift = (int)clk->priv;
410
411	val = __raw_readl(HDMICKCR);
412	mask = ~(0x3 << shift);
413	val = (val & mask) | i << shift;
414	__raw_writel(val, HDMICKCR);
415
416	return 0;
417};
418
419static struct sh_clk_ops hdmi12_clk_ops = {
420	.recalc		= hdmi12_recalc,
421	.set_rate	= hdmi12_set_rate,
422};
423
424static struct clk hdmi1_clk = {
425	.ops		= &hdmi12_clk_ops,
426	.priv		= (void *)9,
427	.parent		= &div6_reparent_clks[DIV6_HDMI],  /* late install */
428};
429
430static struct clk hdmi2_clk = {
431	.ops		= &hdmi12_clk_ops,
432	.priv		= (void *)11,
433	.parent		= &div6_reparent_clks[DIV6_HDMI], /* late install */
434};
435
436static struct clk *late_main_clks[] = {
437	&hdmi1_clk,
438	&hdmi2_clk,
439};
440
441/* FSI DIV */
442enum { FSIDIV_A, FSIDIV_B, FSIDIV_REPARENT_NR };
443
444static struct clk fsidivs[] = {
445	[FSIDIV_A] = SH_CLK_FSIDIV(FSIDIVA, &div6_reparent_clks[DIV6_FSIA]),
446	[FSIDIV_B] = SH_CLK_FSIDIV(FSIDIVB, &div6_reparent_clks[DIV6_FSIB]),
447};
448
449/* MSTP */
450enum {
451	MSTP128, MSTP127, MSTP125,
452	MSTP116, MSTP111, MSTP100, MSTP117,
453
454	MSTP230, MSTP229,
455	MSTP222,
456	MSTP218, MSTP217, MSTP216, MSTP214,
457	MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
458
459	MSTP329, MSTP328, MSTP323, MSTP320,
460	MSTP314, MSTP313, MSTP312,
461	MSTP309, MSTP304,
462
463	MSTP416, MSTP415, MSTP407, MSTP406,
464
465	MSTP_NR
466};
467
468static struct clk mstp_clks[MSTP_NR] = {
469	[MSTP128] = SH_CLK_MSTP32(&div4_clks[DIV4_S],	SMSTPCR1, 28, 0), /* CEU21 */
470	[MSTP127] = SH_CLK_MSTP32(&div4_clks[DIV4_S],	SMSTPCR1, 27, 0), /* CEU20 */
471	[MSTP125] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB],	SMSTPCR1, 25, 0), /* TMU0 */
472	[MSTP117] = SH_CLK_MSTP32(&div4_clks[DIV4_B],	SMSTPCR1, 17, 0), /* LCDC1 */
473	[MSTP116] = SH_CLK_MSTP32(&div4_clks[DIV4_HPP],	SMSTPCR1, 16, 0), /* IIC0 */
474	[MSTP111] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB],	SMSTPCR1, 11, 0), /* TMU1 */
475	[MSTP100] = SH_CLK_MSTP32(&div4_clks[DIV4_B],	SMSTPCR1,  0, 0), /* LCDC0 */
476
477	[MSTP230] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB],	SMSTPCR2, 30, 0), /* SCIFA6 */
478	[MSTP229] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR2, 29, 0), /* INTCA */
479	[MSTP222] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB],	SMSTPCR2, 22, 0), /* SCIFA7 */
480	[MSTP218] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR2, 18, 0), /* DMAC1 */
481	[MSTP217] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR2, 17, 0), /* DMAC2 */
482	[MSTP216] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR2, 16, 0), /* DMAC3 */
483	[MSTP214] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],  SMSTPCR2, 14, 0), /* USBDMAC */
484	[MSTP207] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB],	SMSTPCR2,  7, 0), /* SCIFA5 */
485	[MSTP206] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB],	SMSTPCR2,  6, 0), /* SCIFB */
486	[MSTP204] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB],	SMSTPCR2,  4, 0), /* SCIFA0 */
487	[MSTP203] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB],	SMSTPCR2,  3, 0), /* SCIFA1 */
488	[MSTP202] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB],	SMSTPCR2,  2, 0), /* SCIFA2 */
489	[MSTP201] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB],	SMSTPCR2,  1, 0), /* SCIFA3 */
490	[MSTP200] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB],	SMSTPCR2,  0, 0), /* SCIFA4 */
491
492	[MSTP329] = SH_CLK_MSTP32(&r_clk,		SMSTPCR3, 29, 0), /* CMT10 */
493	[MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR3, 28, 0), /* FSI */
494	[MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB],	SMSTPCR3, 23, 0), /* IIC1 */
495	[MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR3, 20, 0), /* USBF */
496	[MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR3, 14, 0), /* SDHI0 */
497	[MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR3, 13, 0), /* SDHI1 */
498	[MSTP312] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR3, 12, 0), /* MMC */
499	[MSTP309] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR3,  9, 0), /* GEther */
500	[MSTP304] = SH_CLK_MSTP32(&div4_clks[DIV4_CP],	SMSTPCR3,  4, 0), /* TPU0 */
501
502	[MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR4, 16, 0), /* USBHOST */
503	[MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR4, 15, 0), /* SDHI2 */
504	[MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR4,  7, 0), /* USB-Func */
505	[MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP],	SMSTPCR4,  6, 0), /* USB Phy */
506};
507
508static struct clk_lookup lookups[] = {
509	/* main clocks */
510	CLKDEV_CON_ID("extalr",			&extalr_clk),
511	CLKDEV_CON_ID("extal1",			&extal1_clk),
512	CLKDEV_CON_ID("extal2",			&extal2_clk),
513	CLKDEV_CON_ID("extal1_div2",		&extal1_div2_clk),
514	CLKDEV_CON_ID("extal1_div1024",		&extal1_div1024_clk),
515	CLKDEV_CON_ID("extal1_div2048",		&extal1_div2048_clk),
516	CLKDEV_CON_ID("extal2_div2",		&extal2_div2_clk),
517	CLKDEV_CON_ID("dv_clk",			&dv_clk),
518	CLKDEV_CON_ID("system_clk",		&system_clk),
519	CLKDEV_CON_ID("system_div2_clk",	&system_div2_clk),
520	CLKDEV_CON_ID("r_clk",			&r_clk),
521	CLKDEV_CON_ID("pllc0_clk",		&pllc0_clk),
522	CLKDEV_CON_ID("pllc1_clk",		&pllc1_clk),
523	CLKDEV_CON_ID("pllc1_div2_clk",		&pllc1_div2_clk),
524	CLKDEV_CON_ID("usb24s",			&usb24s_clk),
525	CLKDEV_CON_ID("hdmi1",			&hdmi1_clk),
526	CLKDEV_CON_ID("hdmi2",			&hdmi2_clk),
527	CLKDEV_CON_ID("video1",			&div6_reparent_clks[DIV6_VCLK1]),
528	CLKDEV_CON_ID("video2",			&div6_reparent_clks[DIV6_VCLK2]),
529	CLKDEV_CON_ID("fsiack",			&fsiack_clk),
530	CLKDEV_CON_ID("fsibck",			&fsibck_clk),
531
532	/* DIV4 clocks */
533	CLKDEV_CON_ID("i_clk",			&div4_clks[DIV4_I]),
534	CLKDEV_CON_ID("zg_clk",			&div4_clks[DIV4_ZG]),
535	CLKDEV_CON_ID("b_clk",			&div4_clks[DIV4_B]),
536	CLKDEV_CON_ID("m1_clk",			&div4_clks[DIV4_M1]),
537	CLKDEV_CON_ID("hp_clk",			&div4_clks[DIV4_HP]),
538	CLKDEV_CON_ID("hpp_clk",		&div4_clks[DIV4_HPP]),
539	CLKDEV_CON_ID("s_clk",			&div4_clks[DIV4_S]),
540	CLKDEV_CON_ID("zb_clk",			&div4_clks[DIV4_ZB]),
541	CLKDEV_CON_ID("m3_clk",			&div4_clks[DIV4_M3]),
542	CLKDEV_CON_ID("cp_clk",			&div4_clks[DIV4_CP]),
543
544	/* DIV6 clocks */
545	CLKDEV_CON_ID("sub_clk",		&div6_clks[DIV6_SUB]),
546
547	/* MSTP32 clocks */
548	CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0",	&mstp_clks[MSTP100]),
549	CLKDEV_DEV_ID("i2c-sh_mobile.0",	&mstp_clks[MSTP116]),
550	CLKDEV_DEV_ID("fff20000.i2c",		&mstp_clks[MSTP116]),
551	CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1",	&mstp_clks[MSTP117]),
552	CLKDEV_DEV_ID("sh_mobile_ceu.0",	&mstp_clks[MSTP127]),
553	CLKDEV_DEV_ID("sh_mobile_ceu.1",	&mstp_clks[MSTP128]),
554
555	CLKDEV_DEV_ID("sh-sci.4",		&mstp_clks[MSTP200]),
556	CLKDEV_DEV_ID("e6c80000.serial",	&mstp_clks[MSTP200]),
557	CLKDEV_DEV_ID("sh-sci.3",		&mstp_clks[MSTP201]),
558	CLKDEV_DEV_ID("e6c70000.serial",	&mstp_clks[MSTP201]),
559	CLKDEV_DEV_ID("sh-sci.2",		&mstp_clks[MSTP202]),
560	CLKDEV_DEV_ID("e6c60000.serial",	&mstp_clks[MSTP202]),
561	CLKDEV_DEV_ID("sh-sci.1",		&mstp_clks[MSTP203]),
562	CLKDEV_DEV_ID("e6c50000.serial",	&mstp_clks[MSTP203]),
563	CLKDEV_DEV_ID("sh-sci.0",		&mstp_clks[MSTP204]),
564	CLKDEV_DEV_ID("e6c40000.serial",	&mstp_clks[MSTP204]),
565	CLKDEV_DEV_ID("sh-sci.8",		&mstp_clks[MSTP206]),
566	CLKDEV_DEV_ID("e6c30000.serial",	&mstp_clks[MSTP206]),
567	CLKDEV_DEV_ID("sh-sci.5",		&mstp_clks[MSTP207]),
568	CLKDEV_DEV_ID("e6cb0000.serial",	&mstp_clks[MSTP207]),
569	CLKDEV_DEV_ID("sh-dma-engine.3",	&mstp_clks[MSTP214]),
570	CLKDEV_DEV_ID("sh-dma-engine.2",	&mstp_clks[MSTP216]),
571	CLKDEV_DEV_ID("sh-dma-engine.1",	&mstp_clks[MSTP217]),
572	CLKDEV_DEV_ID("sh-dma-engine.0",	&mstp_clks[MSTP218]),
573	CLKDEV_DEV_ID("sh-sci.7",		&mstp_clks[MSTP222]),
574	CLKDEV_DEV_ID("e6cd0000.serial",	&mstp_clks[MSTP222]),
575	CLKDEV_DEV_ID("renesas_intc_irqpin.0",	&mstp_clks[MSTP229]),
576	CLKDEV_DEV_ID("renesas_intc_irqpin.1",	&mstp_clks[MSTP229]),
577	CLKDEV_DEV_ID("renesas_intc_irqpin.2",	&mstp_clks[MSTP229]),
578	CLKDEV_DEV_ID("renesas_intc_irqpin.3",	&mstp_clks[MSTP229]),
579	CLKDEV_DEV_ID("sh-sci.6",		&mstp_clks[MSTP230]),
580	CLKDEV_DEV_ID("e6cc0000.serial",	&mstp_clks[MSTP230]),
581
582	CLKDEV_DEV_ID("sh_fsi2",		&mstp_clks[MSTP328]),
583	CLKDEV_DEV_ID("fe1f0000.sound",		&mstp_clks[MSTP328]),
584	CLKDEV_DEV_ID("i2c-sh_mobile.1",	&mstp_clks[MSTP323]),
585	CLKDEV_DEV_ID("e6c20000.i2c",		&mstp_clks[MSTP323]),
586	CLKDEV_DEV_ID("renesas_usbhs",		&mstp_clks[MSTP320]),
587	CLKDEV_DEV_ID("sh_mobile_sdhi.0",	&mstp_clks[MSTP314]),
588	CLKDEV_DEV_ID("e6850000.sd",		&mstp_clks[MSTP314]),
589	CLKDEV_DEV_ID("sh_mobile_sdhi.1",	&mstp_clks[MSTP313]),
590	CLKDEV_DEV_ID("e6860000.sd",		&mstp_clks[MSTP313]),
591	CLKDEV_DEV_ID("sh_mmcif",		&mstp_clks[MSTP312]),
592	CLKDEV_DEV_ID("e6bd0000.mmc",		&mstp_clks[MSTP312]),
593	CLKDEV_DEV_ID("r8a7740-gether",		&mstp_clks[MSTP309]),
594	CLKDEV_DEV_ID("e9a00000.ethernet",	&mstp_clks[MSTP309]),
595	CLKDEV_DEV_ID("renesas-tpu-pwm",	&mstp_clks[MSTP304]),
596	CLKDEV_DEV_ID("e6600000.pwm",		&mstp_clks[MSTP304]),
597
598	CLKDEV_DEV_ID("sh_mobile_sdhi.2",	&mstp_clks[MSTP415]),
599	CLKDEV_DEV_ID("e6870000.sd",		&mstp_clks[MSTP415]),
600
601	/* ICK */
602	CLKDEV_ICK_ID("fck",	"sh-tmu.1",		&mstp_clks[MSTP111]),
603	CLKDEV_ICK_ID("fck",	"fff90000.timer",	&mstp_clks[MSTP111]),
604	CLKDEV_ICK_ID("fck",	"sh-tmu.0",		&mstp_clks[MSTP125]),
605	CLKDEV_ICK_ID("fck",	"fff80000.timer",	&mstp_clks[MSTP125]),
606	CLKDEV_ICK_ID("fck",	"sh-cmt-48.1",		&mstp_clks[MSTP329]),
607	CLKDEV_ICK_ID("fck",	"e6138000.timer",	&mstp_clks[MSTP329]),
608	CLKDEV_ICK_ID("host",	"renesas_usbhs",	&mstp_clks[MSTP416]),
609	CLKDEV_ICK_ID("func",	"renesas_usbhs",	&mstp_clks[MSTP407]),
610	CLKDEV_ICK_ID("phy",	"renesas_usbhs",	&mstp_clks[MSTP406]),
611	CLKDEV_ICK_ID("pci",	"renesas_usbhs",	&div4_clks[DIV4_USBP]),
612	CLKDEV_ICK_ID("usb24",	"renesas_usbhs",	&usb24_clk),
613	CLKDEV_ICK_ID("ick",	"sh-mobile-hdmi",	&div6_reparent_clks[DIV6_HDMI]),
614
615	CLKDEV_ICK_ID("icka", "sh_fsi2",	&div6_reparent_clks[DIV6_FSIA]),
616	CLKDEV_ICK_ID("ickb", "sh_fsi2",	&div6_reparent_clks[DIV6_FSIB]),
617	CLKDEV_ICK_ID("diva", "sh_fsi2",	&fsidivs[FSIDIV_A]),
618	CLKDEV_ICK_ID("divb", "sh_fsi2",	&fsidivs[FSIDIV_B]),
619	CLKDEV_ICK_ID("xcka", "sh_fsi2",	&fsiack_clk),
620	CLKDEV_ICK_ID("xckb", "sh_fsi2",	&fsibck_clk),
621};
622
623void __init r8a7740_clock_init(u8 md_ck)
624{
625	int k, ret = 0;
626
627	/* detect system clock parent */
628	if (md_ck & MD_CK1)
629		system_clk.parent = &extal1_div2_clk;
630	else
631		system_clk.parent = &extal1_clk;
632
633	/* detect RCLK parent */
634	switch (md_ck & (MD_CK2 | MD_CK1)) {
635	case MD_CK2 | MD_CK1:
636		r_clk.parent = &extal1_div2048_clk;
637		break;
638	case MD_CK2:
639		r_clk.parent = &extal1_div1024_clk;
640		break;
641	case MD_CK1:
642	default:
643		r_clk.parent = &extalr_clk;
644		break;
645	}
646
647	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
648		ret = clk_register(main_clks[k]);
649
650	if (!ret)
651		ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
652
653	if (!ret)
654		ret = sh_clk_div6_register(div6_clks, DIV6_NR);
655
656	if (!ret)
657		ret = sh_clk_div6_reparent_register(div6_reparent_clks,
658						    DIV6_REPARENT_NR);
659
660	if (!ret)
661		ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
662
663	for (k = 0; !ret && (k < ARRAY_SIZE(late_main_clks)); k++)
664		ret = clk_register(late_main_clks[k]);
665
666	if (!ret)
667		ret = sh_clk_fsidiv_register(fsidivs, FSIDIV_REPARENT_NR);
668
669	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
670
671	if (!ret)
672		shmobile_clk_init();
673	else
674		panic("failed to setup r8a7740 clocks\n");
675}
676