1/*
2 * r8a7779 clock framework support
3 *
4 * Copyright (C) 2011  Renesas Solutions Corp.
5 * Copyright (C) 2011  Magnus Damm
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/bitops.h>
17#include <linux/init.h>
18#include <linux/kernel.h>
19#include <linux/io.h>
20#include <linux/sh_clk.h>
21#include <linux/clkdev.h>
22#include <linux/sh_timer.h>
23
24#include "clock.h"
25#include "common.h"
26#include "r8a7779.h"
27
28/*
29 *		MD1 = 1			MD1 = 0
30 *		(PLLA = 1500)		(PLLA = 1600)
31 *		(MHz)			(MHz)
32 *------------------------------------------------+--------------------
33 * clkz		1000   (2/3)		800   (1/2)
34 * clkzs	 250   (1/6)		200   (1/8)
35 * clki		 750   (1/2)		800   (1/2)
36 * clks		 250   (1/6)		200   (1/8)
37 * clks1	 125   (1/12)		100   (1/16)
38 * clks3	 187.5 (1/8)		200   (1/8)
39 * clks4	  93.7 (1/16)		100   (1/16)
40 * clkp		  62.5 (1/24)		 50   (1/32)
41 * clkg		  62.5 (1/24)		 66.6 (1/24)
42 * clkb, CLKOUT
43 * (MD2 = 0)	  62.5 (1/24)		 66.6 (1/24)
44 * (MD2 = 1)	  41.6 (1/36)		 50   (1/32)
45*/
46
47#define MD(nr)	BIT(nr)
48
49#define MSTPCR0		IOMEM(0xffc80030)
50#define MSTPCR1		IOMEM(0xffc80034)
51#define MSTPCR3		IOMEM(0xffc8003c)
52#define MSTPSR1		IOMEM(0xffc80044)
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
63/*
64 * Default rate for the root input clock, reset this with clk_set_rate()
65 * from the platform code.
66 */
67static struct clk plla_clk = {
68	/* .rate will be updated on r8a7779_clock_init() */
69	.mapping	= &cpg_mapping,
70};
71
72/*
73 * clock ratio of these clock will be updated
74 * on r8a7779_clock_init()
75 */
76SH_FIXED_RATIO_CLK_SET(clkz_clk,	plla_clk, 1, 1);
77SH_FIXED_RATIO_CLK_SET(clkzs_clk,	plla_clk, 1, 1);
78SH_FIXED_RATIO_CLK_SET(clki_clk,	plla_clk, 1, 1);
79SH_FIXED_RATIO_CLK_SET(clks_clk,	plla_clk, 1, 1);
80SH_FIXED_RATIO_CLK_SET(clks1_clk,	plla_clk, 1, 1);
81SH_FIXED_RATIO_CLK_SET(clks3_clk,	plla_clk, 1, 1);
82SH_FIXED_RATIO_CLK_SET(clks4_clk,	plla_clk, 1, 1);
83SH_FIXED_RATIO_CLK_SET(clkb_clk,	plla_clk, 1, 1);
84SH_FIXED_RATIO_CLK_SET(clkout_clk,	plla_clk, 1, 1);
85SH_FIXED_RATIO_CLK_SET(clkp_clk,	plla_clk, 1, 1);
86SH_FIXED_RATIO_CLK_SET(clkg_clk,	plla_clk, 1, 1);
87
88static struct clk *main_clks[] = {
89	&plla_clk,
90	&clkz_clk,
91	&clkzs_clk,
92	&clki_clk,
93	&clks_clk,
94	&clks1_clk,
95	&clks3_clk,
96	&clks4_clk,
97	&clkb_clk,
98	&clkout_clk,
99	&clkp_clk,
100	&clkg_clk,
101};
102
103enum { MSTP323, MSTP322, MSTP321, MSTP320,
104	MSTP120,
105	MSTP116, MSTP115, MSTP114,
106	MSTP110, MSTP109, MSTP108,
107	MSTP103, MSTP101, MSTP100,
108	MSTP030,
109	MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
110	MSTP016, MSTP015, MSTP014,
111	MSTP007,
112	MSTP_NR };
113
114static struct clk mstp_clks[MSTP_NR] = {
115	[MSTP323] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 23, 0), /* SDHI0 */
116	[MSTP322] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 22, 0), /* SDHI1 */
117	[MSTP321] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 21, 0), /* SDHI2 */
118	[MSTP320] = SH_CLK_MSTP32(&clkp_clk, MSTPCR3, 20, 0), /* SDHI3 */
119	[MSTP120] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1, 20, MSTPSR1, 0), /* VIN3 */
120	[MSTP116] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1, 16, MSTPSR1, 0), /* PCIe */
121	[MSTP115] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1, 15, MSTPSR1, 0), /* SATA */
122	[MSTP114] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1, 14, MSTPSR1, 0), /* Ether */
123	[MSTP110] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1, 10, MSTPSR1, 0), /* VIN0 */
124	[MSTP109] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1,  9, MSTPSR1, 0), /* VIN1 */
125	[MSTP108] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1,  8, MSTPSR1, 0), /* VIN2 */
126	[MSTP103] = SH_CLK_MSTP32_STS(&clks_clk, MSTPCR1,  3, MSTPSR1, 0), /* DU */
127	[MSTP101] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1,  1, MSTPSR1, 0), /* USB2 */
128	[MSTP100] = SH_CLK_MSTP32_STS(&clkp_clk, MSTPCR1,  0, MSTPSR1, 0), /* USB0/1 */
129	[MSTP030] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 30, 0), /* I2C0 */
130	[MSTP029] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 29, 0), /* I2C1 */
131	[MSTP028] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 28, 0), /* I2C2 */
132	[MSTP027] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 27, 0), /* I2C3 */
133	[MSTP026] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 26, 0), /* SCIF0 */
134	[MSTP025] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 25, 0), /* SCIF1 */
135	[MSTP024] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 24, 0), /* SCIF2 */
136	[MSTP023] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 23, 0), /* SCIF3 */
137	[MSTP022] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 22, 0), /* SCIF4 */
138	[MSTP021] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 21, 0), /* SCIF5 */
139	[MSTP016] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 16, 0), /* TMU0 */
140	[MSTP015] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 15, 0), /* TMU1 */
141	[MSTP014] = SH_CLK_MSTP32(&clkp_clk, MSTPCR0, 14, 0), /* TMU2 */
142	[MSTP007] = SH_CLK_MSTP32(&clks_clk, MSTPCR0,  7, 0), /* HSPI */
143};
144
145static struct clk_lookup lookups[] = {
146	/* main clocks */
147	CLKDEV_CON_ID("plla_clk", &plla_clk),
148	CLKDEV_CON_ID("clkz_clk", &clkz_clk),
149	CLKDEV_CON_ID("clkzs_clk", &clkzs_clk),
150
151	/* DIV4 clocks */
152	CLKDEV_CON_ID("shyway_clk",	&clks_clk),
153	CLKDEV_CON_ID("bus_clk",	&clkout_clk),
154	CLKDEV_CON_ID("shyway4_clk",	&clks4_clk),
155	CLKDEV_CON_ID("shyway3_clk",	&clks3_clk),
156	CLKDEV_CON_ID("shyway1_clk",	&clks1_clk),
157	CLKDEV_CON_ID("peripheral_clk",	&clkp_clk),
158
159	/* MSTP32 clocks */
160	CLKDEV_DEV_ID("r8a7779-vin.3", &mstp_clks[MSTP120]), /* VIN3 */
161	CLKDEV_DEV_ID("rcar-pcie", &mstp_clks[MSTP116]), /* PCIe */
162	CLKDEV_DEV_ID("sata_rcar", &mstp_clks[MSTP115]), /* SATA */
163	CLKDEV_DEV_ID("fc600000.sata", &mstp_clks[MSTP115]), /* SATA w/DT */
164	CLKDEV_DEV_ID("r8a777x-ether", &mstp_clks[MSTP114]), /* Ether */
165	CLKDEV_DEV_ID("r8a7779-vin.0", &mstp_clks[MSTP110]), /* VIN0 */
166	CLKDEV_DEV_ID("r8a7779-vin.1", &mstp_clks[MSTP109]), /* VIN1 */
167	CLKDEV_DEV_ID("r8a7779-vin.2", &mstp_clks[MSTP108]), /* VIN2 */
168	CLKDEV_DEV_ID("ehci-platform.1", &mstp_clks[MSTP101]), /* USB EHCI port2 */
169	CLKDEV_DEV_ID("ohci-platform.1", &mstp_clks[MSTP101]), /* USB OHCI port2 */
170	CLKDEV_DEV_ID("ehci-platform.0", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */
171	CLKDEV_DEV_ID("ohci-platform.0", &mstp_clks[MSTP100]), /* USB OHCI port0/1 */
172	CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP016]), /* TMU0 */
173	CLKDEV_DEV_ID("i2c-rcar.0", &mstp_clks[MSTP030]), /* I2C0 */
174	CLKDEV_DEV_ID("ffc70000.i2c", &mstp_clks[MSTP030]), /* I2C0 */
175	CLKDEV_DEV_ID("i2c-rcar.1", &mstp_clks[MSTP029]), /* I2C1 */
176	CLKDEV_DEV_ID("ffc71000.i2c", &mstp_clks[MSTP029]), /* I2C1 */
177	CLKDEV_DEV_ID("i2c-rcar.2", &mstp_clks[MSTP028]), /* I2C2 */
178	CLKDEV_DEV_ID("ffc72000.i2c", &mstp_clks[MSTP028]), /* I2C2 */
179	CLKDEV_DEV_ID("i2c-rcar.3", &mstp_clks[MSTP027]), /* I2C3 */
180	CLKDEV_DEV_ID("ffc73000.i2c", &mstp_clks[MSTP027]), /* I2C3 */
181	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
182	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
183	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */
184	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP023]), /* SCIF3 */
185	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP022]), /* SCIF4 */
186	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP021]), /* SCIF6 */
187	CLKDEV_DEV_ID("sh-hspi.0", &mstp_clks[MSTP007]), /* HSPI0 */
188	CLKDEV_DEV_ID("fffc7000.spi", &mstp_clks[MSTP007]), /* HSPI0 */
189	CLKDEV_DEV_ID("sh-hspi.1", &mstp_clks[MSTP007]), /* HSPI1 */
190	CLKDEV_DEV_ID("fffc8000.spi", &mstp_clks[MSTP007]), /* HSPI1 */
191	CLKDEV_DEV_ID("sh-hspi.2", &mstp_clks[MSTP007]), /* HSPI2 */
192	CLKDEV_DEV_ID("fffc6000.spi", &mstp_clks[MSTP007]), /* HSPI2 */
193	CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP323]), /* SDHI0 */
194	CLKDEV_DEV_ID("ffe4c000.sd", &mstp_clks[MSTP323]), /* SDHI0 */
195	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
196	CLKDEV_DEV_ID("ffe4d000.sd", &mstp_clks[MSTP322]), /* SDHI1 */
197	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
198	CLKDEV_DEV_ID("ffe4e000.sd", &mstp_clks[MSTP321]), /* SDHI2 */
199	CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP320]), /* SDHI3 */
200	CLKDEV_DEV_ID("ffe4f000.sd", &mstp_clks[MSTP320]), /* SDHI3 */
201	CLKDEV_DEV_ID("rcar-du-r8a7779", &mstp_clks[MSTP103]), /* DU */
202};
203
204void __init r8a7779_clock_init(void)
205{
206	u32 mode = r8a7779_read_mode_pins();
207	int k, ret = 0;
208
209	if (mode & MD(1)) {
210		plla_clk.rate = 1500000000;
211
212		SH_CLK_SET_RATIO(&clkz_clk_ratio,	2, 3);
213		SH_CLK_SET_RATIO(&clkzs_clk_ratio,	1, 6);
214		SH_CLK_SET_RATIO(&clki_clk_ratio,	1, 2);
215		SH_CLK_SET_RATIO(&clks_clk_ratio,	1, 6);
216		SH_CLK_SET_RATIO(&clks1_clk_ratio,	1, 12);
217		SH_CLK_SET_RATIO(&clks3_clk_ratio,	1, 8);
218		SH_CLK_SET_RATIO(&clks4_clk_ratio,	1, 16);
219		SH_CLK_SET_RATIO(&clkp_clk_ratio,	1, 24);
220		SH_CLK_SET_RATIO(&clkg_clk_ratio,	1, 24);
221		if (mode & MD(2)) {
222			SH_CLK_SET_RATIO(&clkb_clk_ratio,	1, 36);
223			SH_CLK_SET_RATIO(&clkout_clk_ratio,	1, 36);
224		} else {
225			SH_CLK_SET_RATIO(&clkb_clk_ratio,	1, 24);
226			SH_CLK_SET_RATIO(&clkout_clk_ratio,	1, 24);
227		}
228	} else {
229		plla_clk.rate = 1600000000;
230
231		SH_CLK_SET_RATIO(&clkz_clk_ratio,	1, 2);
232		SH_CLK_SET_RATIO(&clkzs_clk_ratio,	1, 8);
233		SH_CLK_SET_RATIO(&clki_clk_ratio,	1, 2);
234		SH_CLK_SET_RATIO(&clks_clk_ratio,	1, 8);
235		SH_CLK_SET_RATIO(&clks1_clk_ratio,	1, 16);
236		SH_CLK_SET_RATIO(&clks3_clk_ratio,	1, 8);
237		SH_CLK_SET_RATIO(&clks4_clk_ratio,	1, 16);
238		SH_CLK_SET_RATIO(&clkp_clk_ratio,	1, 32);
239		SH_CLK_SET_RATIO(&clkg_clk_ratio,	1, 24);
240		if (mode & MD(2)) {
241			SH_CLK_SET_RATIO(&clkb_clk_ratio,	1, 32);
242			SH_CLK_SET_RATIO(&clkout_clk_ratio,	1, 32);
243		} else {
244			SH_CLK_SET_RATIO(&clkb_clk_ratio,	1, 24);
245			SH_CLK_SET_RATIO(&clkout_clk_ratio,	1, 24);
246		}
247	}
248
249	for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
250		ret = clk_register(main_clks[k]);
251
252	if (!ret)
253		ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
254
255	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
256
257	if (!ret)
258		shmobile_clk_init();
259	else
260		panic("failed to setup r8a7779 clocks\n");
261}
262
263/* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
264void __init __weak r8a7779_register_twd(void) { }
265
266void __init r8a7779_earlytimer_init(void)
267{
268	r8a7779_clock_init();
269	r8a7779_register_twd();
270	shmobile_earlytimer_init();
271}
272