1/*
2 * r8a7778 clock framework support
3 *
4 * Copyright (C) 2013  Renesas Solutions Corp.
5 * Copyright (C) 2013  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6 *
7 * based on r8a7779
8 *
9 * Copyright (C) 2011  Renesas Solutions Corp.
10 * Copyright (C) 2011  Magnus Damm
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU General Public License for more details.
20 */
21
22/*
23 *     MD      MD      MD      MD       PLLA   PLLB    EXTAL   clki    clkz
24 *     19      18      12      11                      (HMz)   (MHz)   (MHz)
25 *----------------------------------------------------------------------------
26 *     1       0       0       0       x21     x21     38.00   800     800
27 *     1       0       0       1       x24     x24     33.33   800     800
28 *     1       0       1       0       x28     x28     28.50   800     800
29 *     1       0       1       1       x32     x32     25.00   800     800
30 *     1       1       0       1       x24     x21     33.33   800     700
31 *     1       1       1       0       x28     x21     28.50   800     600
32 *     1       1       1       1       x32     x24     25.00   800     600
33 */
34
35#include <linux/io.h>
36#include <linux/sh_clk.h>
37#include <linux/clkdev.h>
38#include "clock.h"
39#include "common.h"
40
41#define MSTPCR0		IOMEM(0xffc80030)
42#define MSTPCR1		IOMEM(0xffc80034)
43#define MSTPCR3		IOMEM(0xffc8003c)
44#define MSTPSR1		IOMEM(0xffc80044)
45#define MSTPSR4		IOMEM(0xffc80048)
46#define MSTPSR6		IOMEM(0xffc8004c)
47#define MSTPCR4		IOMEM(0xffc80050)
48#define MSTPCR5		IOMEM(0xffc80054)
49#define MSTPCR6		IOMEM(0xffc80058)
50#define MODEMR		0xFFCC0020
51
52#define MD(nr)	BIT(nr)
53
54/* ioremap() through clock mapping mandatory to avoid
55 * collision with ARM coherent DMA virtual memory range.
56 */
57
58static struct clk_mapping cpg_mapping = {
59	.phys	= 0xffc80000,
60	.len	= 0x80,
61};
62
63static struct clk extal_clk = {
64	/* .rate will be updated on r8a7778_clock_init() */
65	.mapping = &cpg_mapping,
66};
67
68static struct clk audio_clk_a = {
69};
70
71static struct clk audio_clk_b = {
72};
73
74static struct clk audio_clk_c = {
75};
76
77/*
78 * clock ratio of these clock will be updated
79 * on r8a7778_clock_init()
80 */
81SH_FIXED_RATIO_CLK_SET(plla_clk,	extal_clk, 1, 1);
82SH_FIXED_RATIO_CLK_SET(pllb_clk,	extal_clk, 1, 1);
83SH_FIXED_RATIO_CLK_SET(i_clk,		plla_clk,  1, 1);
84SH_FIXED_RATIO_CLK_SET(s_clk,		plla_clk,  1, 1);
85SH_FIXED_RATIO_CLK_SET(s1_clk,		plla_clk,  1, 1);
86SH_FIXED_RATIO_CLK_SET(s3_clk,		plla_clk,  1, 1);
87SH_FIXED_RATIO_CLK_SET(s4_clk,		plla_clk,  1, 1);
88SH_FIXED_RATIO_CLK_SET(b_clk,		plla_clk,  1, 1);
89SH_FIXED_RATIO_CLK_SET(out_clk,		plla_clk,  1, 1);
90SH_FIXED_RATIO_CLK_SET(p_clk,		plla_clk,  1, 1);
91SH_FIXED_RATIO_CLK_SET(g_clk,		plla_clk,  1, 1);
92SH_FIXED_RATIO_CLK_SET(z_clk,		pllb_clk,  1, 1);
93
94static struct clk *main_clks[] = {
95	&extal_clk,
96	&plla_clk,
97	&pllb_clk,
98	&i_clk,
99	&s_clk,
100	&s1_clk,
101	&s3_clk,
102	&s4_clk,
103	&b_clk,
104	&out_clk,
105	&p_clk,
106	&g_clk,
107	&z_clk,
108	&audio_clk_a,
109	&audio_clk_b,
110	&audio_clk_c,
111};
112
113enum {
114	MSTP531, MSTP530,
115	MSTP529, MSTP528, MSTP527, MSTP526, MSTP525, MSTP524, MSTP523,
116	MSTP331,
117	MSTP323, MSTP322, MSTP321,
118	MSTP311, MSTP310,
119	MSTP309, MSTP308, MSTP307,
120	MSTP114,
121	MSTP110, MSTP109,
122	MSTP100,
123	MSTP030,
124	MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
125	MSTP016, MSTP015, MSTP012, MSTP011, MSTP010,
126	MSTP009, MSTP008, MSTP007,
127	MSTP_NR };
128
129static struct clk mstp_clks[MSTP_NR] = {
130	[MSTP531] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 31, 0), /* SCU0 */
131	[MSTP530] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 30, 0), /* SCU1 */
132	[MSTP529] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 29, 0), /* SCU2 */
133	[MSTP528] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 28, 0), /* SCU3 */
134	[MSTP527] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 27, 0), /* SCU4 */
135	[MSTP526] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 26, 0), /* SCU5 */
136	[MSTP525] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 25, 0), /* SCU6 */
137	[MSTP524] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 24, 0), /* SCU7 */
138	[MSTP523] = SH_CLK_MSTP32(&p_clk, MSTPCR5, 23, 0), /* SCU8 */
139	[MSTP331] = SH_CLK_MSTP32(&s4_clk, MSTPCR3, 31, 0), /* MMC */
140	[MSTP323] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 23, 0), /* SDHI0 */
141	[MSTP322] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 22, 0), /* SDHI1 */
142	[MSTP321] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 21, 0), /* SDHI2 */
143	[MSTP311] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 11, 0), /* SSI4 */
144	[MSTP310] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 10, 0), /* SSI5 */
145	[MSTP309] = SH_CLK_MSTP32(&p_clk, MSTPCR3,  9, 0), /* SSI6 */
146	[MSTP308] = SH_CLK_MSTP32(&p_clk, MSTPCR3,  8, 0), /* SSI7 */
147	[MSTP307] = SH_CLK_MSTP32(&p_clk, MSTPCR3,  7, 0), /* SSI8 */
148	[MSTP114] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 14, 0), /* Ether */
149	[MSTP110] = SH_CLK_MSTP32(&s_clk, MSTPCR1, 10, 0), /* VIN0 */
150	[MSTP109] = SH_CLK_MSTP32(&s_clk, MSTPCR1,  9, 0), /* VIN1 */
151	[MSTP100] = SH_CLK_MSTP32(&p_clk, MSTPCR1,  0, 0), /* USB0/1 */
152	[MSTP030] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 30, 0), /* I2C0 */
153	[MSTP029] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 29, 0), /* I2C1 */
154	[MSTP028] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 28, 0), /* I2C2 */
155	[MSTP027] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 27, 0), /* I2C3 */
156	[MSTP026] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 26, 0), /* SCIF0 */
157	[MSTP025] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 25, 0), /* SCIF1 */
158	[MSTP024] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 24, 0), /* SCIF2 */
159	[MSTP023] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 23, 0), /* SCIF3 */
160	[MSTP022] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 22, 0), /* SCIF4 */
161	[MSTP021] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 21, 0), /* SCIF5 */
162	[MSTP016] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 16, 0), /* TMU0 */
163	[MSTP015] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 15, 0), /* TMU1 */
164	[MSTP012] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 12, 0), /* SSI0 */
165	[MSTP011] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 11, 0), /* SSI1 */
166	[MSTP010] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 10, 0), /* SSI2 */
167	[MSTP009] = SH_CLK_MSTP32(&p_clk, MSTPCR0,  9, 0), /* SSI3 */
168	[MSTP008] = SH_CLK_MSTP32(&p_clk, MSTPCR0,  8, 0), /* SRU */
169	[MSTP007] = SH_CLK_MSTP32(&s_clk, MSTPCR0,  7, 0), /* HSPI */
170};
171
172static struct clk_lookup lookups[] = {
173	/* main */
174	CLKDEV_CON_ID("shyway_clk",	&s_clk),
175	CLKDEV_CON_ID("peripheral_clk",	&p_clk),
176
177	/* MSTP32 clocks */
178	CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP331]), /* MMC */
179	CLKDEV_DEV_ID("ffe4e000.mmc", &mstp_clks[MSTP331]), /* MMC */
180	CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP323]), /* SDHI0 */
181	CLKDEV_DEV_ID("ffe4c000.sd", &mstp_clks[MSTP323]), /* SDHI0 */
182	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
183	CLKDEV_DEV_ID("ffe4d000.sd", &mstp_clks[MSTP322]), /* SDHI1 */
184	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
185	CLKDEV_DEV_ID("ffe4f000.sd", &mstp_clks[MSTP321]), /* SDHI2 */
186	CLKDEV_DEV_ID("r8a777x-ether", &mstp_clks[MSTP114]), /* Ether */
187	CLKDEV_DEV_ID("r8a7778-vin.0", &mstp_clks[MSTP110]), /* VIN0 */
188	CLKDEV_DEV_ID("r8a7778-vin.1", &mstp_clks[MSTP109]), /* VIN1 */
189	CLKDEV_DEV_ID("ehci-platform", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */
190	CLKDEV_DEV_ID("ohci-platform", &mstp_clks[MSTP100]), /* USB OHCI port0/1 */
191	CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP100]), /* USB FUNC */
192	CLKDEV_DEV_ID("i2c-rcar.0", &mstp_clks[MSTP030]), /* I2C0 */
193	CLKDEV_DEV_ID("ffc70000.i2c", &mstp_clks[MSTP030]), /* I2C0 */
194	CLKDEV_DEV_ID("i2c-rcar.1", &mstp_clks[MSTP029]), /* I2C1 */
195	CLKDEV_DEV_ID("ffc71000.i2c", &mstp_clks[MSTP029]), /* I2C1 */
196	CLKDEV_DEV_ID("i2c-rcar.2", &mstp_clks[MSTP028]), /* I2C2 */
197	CLKDEV_DEV_ID("ffc72000.i2c", &mstp_clks[MSTP028]), /* I2C2 */
198	CLKDEV_DEV_ID("i2c-rcar.3", &mstp_clks[MSTP027]), /* I2C3 */
199	CLKDEV_DEV_ID("ffc73000.i2c", &mstp_clks[MSTP027]), /* I2C3 */
200	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
201	CLKDEV_DEV_ID("ffe40000.serial", &mstp_clks[MSTP026]), /* SCIF0 */
202	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
203	CLKDEV_DEV_ID("ffe41000.serial", &mstp_clks[MSTP025]), /* SCIF1 */
204	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */
205	CLKDEV_DEV_ID("ffe42000.serial", &mstp_clks[MSTP024]), /* SCIF2 */
206	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP023]), /* SCIF3 */
207	CLKDEV_DEV_ID("ffe43000.serial", &mstp_clks[MSTP023]), /* SCIF3 */
208	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP022]), /* SCIF4 */
209	CLKDEV_DEV_ID("ffe44000.serial", &mstp_clks[MSTP022]), /* SCIF4 */
210	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP021]), /* SCIF6 */
211	CLKDEV_DEV_ID("ffe45000.serial", &mstp_clks[MSTP021]), /* SCIF5 */
212	CLKDEV_DEV_ID("sh-hspi.0", &mstp_clks[MSTP007]), /* HSPI0 */
213	CLKDEV_DEV_ID("fffc7000.spi", &mstp_clks[MSTP007]), /* HSPI0 */
214	CLKDEV_DEV_ID("sh-hspi.1", &mstp_clks[MSTP007]), /* HSPI1 */
215	CLKDEV_DEV_ID("fffc8000.spi", &mstp_clks[MSTP007]), /* HSPI1 */
216	CLKDEV_DEV_ID("sh-hspi.2", &mstp_clks[MSTP007]), /* HSPI2 */
217	CLKDEV_DEV_ID("fffc6000.spi", &mstp_clks[MSTP007]), /* HSPI2 */
218	CLKDEV_DEV_ID("rcar_sound", &mstp_clks[MSTP008]), /* SRU */
219
220	CLKDEV_ICK_ID("clk_a", "rcar_sound", &audio_clk_a),
221	CLKDEV_ICK_ID("clk_b", "rcar_sound", &audio_clk_b),
222	CLKDEV_ICK_ID("clk_c", "rcar_sound", &audio_clk_c),
223	CLKDEV_ICK_ID("clk_i", "rcar_sound", &s1_clk),
224	CLKDEV_ICK_ID("ssi.0", "rcar_sound", &mstp_clks[MSTP012]),
225	CLKDEV_ICK_ID("ssi.1", "rcar_sound", &mstp_clks[MSTP011]),
226	CLKDEV_ICK_ID("ssi.2", "rcar_sound", &mstp_clks[MSTP010]),
227	CLKDEV_ICK_ID("ssi.3", "rcar_sound", &mstp_clks[MSTP009]),
228	CLKDEV_ICK_ID("ssi.4", "rcar_sound", &mstp_clks[MSTP311]),
229	CLKDEV_ICK_ID("ssi.5", "rcar_sound", &mstp_clks[MSTP310]),
230	CLKDEV_ICK_ID("ssi.6", "rcar_sound", &mstp_clks[MSTP309]),
231	CLKDEV_ICK_ID("ssi.7", "rcar_sound", &mstp_clks[MSTP308]),
232	CLKDEV_ICK_ID("ssi.8", "rcar_sound", &mstp_clks[MSTP307]),
233	CLKDEV_ICK_ID("src.0", "rcar_sound", &mstp_clks[MSTP531]),
234	CLKDEV_ICK_ID("src.1", "rcar_sound", &mstp_clks[MSTP530]),
235	CLKDEV_ICK_ID("src.2", "rcar_sound", &mstp_clks[MSTP529]),
236	CLKDEV_ICK_ID("src.3", "rcar_sound", &mstp_clks[MSTP528]),
237	CLKDEV_ICK_ID("src.4", "rcar_sound", &mstp_clks[MSTP527]),
238	CLKDEV_ICK_ID("src.5", "rcar_sound", &mstp_clks[MSTP526]),
239	CLKDEV_ICK_ID("src.6", "rcar_sound", &mstp_clks[MSTP525]),
240	CLKDEV_ICK_ID("src.7", "rcar_sound", &mstp_clks[MSTP524]),
241	CLKDEV_ICK_ID("src.8", "rcar_sound", &mstp_clks[MSTP523]),
242	CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP016]),
243	CLKDEV_ICK_ID("fck", "ffd80000.timer", &mstp_clks[MSTP016]),
244	CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP015]),
245	CLKDEV_ICK_ID("fck", "ffd81000.timer", &mstp_clks[MSTP015]),
246};
247
248void __init r8a7778_clock_init(void)
249{
250	void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
251	u32 mode;
252	int k, ret = 0;
253
254	BUG_ON(!modemr);
255	mode = ioread32(modemr);
256	iounmap(modemr);
257
258	switch (mode & (MD(19) | MD(18) | MD(12) | MD(11))) {
259	case MD(19):
260		extal_clk.rate = 38000000;
261		SH_CLK_SET_RATIO(&plla_clk_ratio,	21, 1);
262		SH_CLK_SET_RATIO(&pllb_clk_ratio,	21, 1);
263		break;
264	case MD(19) | MD(11):
265		extal_clk.rate = 33333333;
266		SH_CLK_SET_RATIO(&plla_clk_ratio,	24, 1);
267		SH_CLK_SET_RATIO(&pllb_clk_ratio,	24, 1);
268		break;
269	case MD(19) | MD(12):
270		extal_clk.rate = 28500000;
271		SH_CLK_SET_RATIO(&plla_clk_ratio,	28, 1);
272		SH_CLK_SET_RATIO(&pllb_clk_ratio,	28, 1);
273		break;
274	case MD(19) | MD(12) | MD(11):
275		extal_clk.rate = 25000000;
276		SH_CLK_SET_RATIO(&plla_clk_ratio,	32, 1);
277		SH_CLK_SET_RATIO(&pllb_clk_ratio,	32, 1);
278		break;
279	case MD(19) | MD(18) | MD(11):
280		extal_clk.rate = 33333333;
281		SH_CLK_SET_RATIO(&plla_clk_ratio,	24, 1);
282		SH_CLK_SET_RATIO(&pllb_clk_ratio,	21, 1);
283		break;
284	case MD(19) | MD(18) | MD(12):
285		extal_clk.rate = 28500000;
286		SH_CLK_SET_RATIO(&plla_clk_ratio,	28, 1);
287		SH_CLK_SET_RATIO(&pllb_clk_ratio,	21, 1);
288		break;
289	case MD(19) | MD(18) | MD(12) | MD(11):
290		extal_clk.rate = 25000000;
291		SH_CLK_SET_RATIO(&plla_clk_ratio,	32, 1);
292		SH_CLK_SET_RATIO(&pllb_clk_ratio,	24, 1);
293		break;
294	default:
295		BUG();
296	}
297
298	if (mode & MD(1)) {
299		SH_CLK_SET_RATIO(&i_clk_ratio,	1, 1);
300		SH_CLK_SET_RATIO(&s_clk_ratio,	1, 3);
301		SH_CLK_SET_RATIO(&s1_clk_ratio,	1, 6);
302		SH_CLK_SET_RATIO(&s3_clk_ratio,	1, 4);
303		SH_CLK_SET_RATIO(&s4_clk_ratio,	1, 8);
304		SH_CLK_SET_RATIO(&p_clk_ratio,	1, 12);
305		SH_CLK_SET_RATIO(&g_clk_ratio,	1, 12);
306		if (mode & MD(2)) {
307			SH_CLK_SET_RATIO(&b_clk_ratio,		1, 18);
308			SH_CLK_SET_RATIO(&out_clk_ratio,	1, 18);
309		} else {
310			SH_CLK_SET_RATIO(&b_clk_ratio,		1, 12);
311			SH_CLK_SET_RATIO(&out_clk_ratio,	1, 12);
312		}
313	} else {
314		SH_CLK_SET_RATIO(&i_clk_ratio,	1, 1);
315		SH_CLK_SET_RATIO(&s_clk_ratio,	1, 4);
316		SH_CLK_SET_RATIO(&s1_clk_ratio,	1, 8);
317		SH_CLK_SET_RATIO(&s3_clk_ratio,	1, 4);
318		SH_CLK_SET_RATIO(&s4_clk_ratio,	1, 8);
319		SH_CLK_SET_RATIO(&p_clk_ratio,	1, 16);
320		SH_CLK_SET_RATIO(&g_clk_ratio,	1, 12);
321		if (mode & MD(2)) {
322			SH_CLK_SET_RATIO(&b_clk_ratio,		1, 16);
323			SH_CLK_SET_RATIO(&out_clk_ratio,	1, 16);
324		} else {
325			SH_CLK_SET_RATIO(&b_clk_ratio,		1, 12);
326			SH_CLK_SET_RATIO(&out_clk_ratio,	1, 12);
327		}
328	}
329
330	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
331		ret = clk_register(main_clks[k]);
332
333	if (!ret)
334		ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
335
336	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
337
338	if (!ret)
339		shmobile_clk_init();
340	else
341		panic("failed to setup r8a7778 clocks\n");
342}
343