Merge tag 'omap-for-v3.13/board-signed' of git://git.kernel.org/pub/scm/linux/kernel...
[platform/adaptation/renesas_rcar/renesas_kernel.git] / arch / arm / mach-shmobile / clock-r8a7778.c
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  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26 /*
27  *     MD      MD      MD      MD       PLLA   PLLB    EXTAL   clki    clkz
28  *     19      18      12      11                      (HMz)   (MHz)   (MHz)
29  *----------------------------------------------------------------------------
30  *     1       0       0       0       x21     x21     38.00   800     800
31  *     1       0       0       1       x24     x24     33.33   800     800
32  *     1       0       1       0       x28     x28     28.50   800     800
33  *     1       0       1       1       x32     x32     25.00   800     800
34  *     1       1       0       1       x24     x21     33.33   800     700
35  *     1       1       1       0       x28     x21     28.50   800     600
36  *     1       1       1       1       x32     x24     25.00   800     600
37  */
38
39 #include <linux/io.h>
40 #include <linux/sh_clk.h>
41 #include <linux/clkdev.h>
42 #include <mach/clock.h>
43 #include <mach/common.h>
44
45 #define MSTPCR0         IOMEM(0xffc80030)
46 #define MSTPCR1         IOMEM(0xffc80034)
47 #define MSTPCR3         IOMEM(0xffc8003c)
48 #define MSTPSR1         IOMEM(0xffc80044)
49 #define MSTPSR4         IOMEM(0xffc80048)
50 #define MSTPSR6         IOMEM(0xffc8004c)
51 #define MSTPCR4         IOMEM(0xffc80050)
52 #define MSTPCR5         IOMEM(0xffc80054)
53 #define MSTPCR6         IOMEM(0xffc80058)
54 #define MODEMR          0xFFCC0020
55
56 #define MD(nr)  BIT(nr)
57
58 /* ioremap() through clock mapping mandatory to avoid
59  * collision with ARM coherent DMA virtual memory range.
60  */
61
62 static struct clk_mapping cpg_mapping = {
63         .phys   = 0xffc80000,
64         .len    = 0x80,
65 };
66
67 static struct clk extal_clk = {
68         /* .rate will be updated on r8a7778_clock_init() */
69         .mapping = &cpg_mapping,
70 };
71
72 static struct clk audio_clk_a = {
73 };
74
75 static struct clk audio_clk_b = {
76 };
77
78 static struct clk audio_clk_c = {
79 };
80
81 /*
82  * clock ratio of these clock will be updated
83  * on r8a7778_clock_init()
84  */
85 SH_FIXED_RATIO_CLK_SET(plla_clk,        extal_clk, 1, 1);
86 SH_FIXED_RATIO_CLK_SET(pllb_clk,        extal_clk, 1, 1);
87 SH_FIXED_RATIO_CLK_SET(i_clk,           plla_clk,  1, 1);
88 SH_FIXED_RATIO_CLK_SET(s_clk,           plla_clk,  1, 1);
89 SH_FIXED_RATIO_CLK_SET(s1_clk,          plla_clk,  1, 1);
90 SH_FIXED_RATIO_CLK_SET(s3_clk,          plla_clk,  1, 1);
91 SH_FIXED_RATIO_CLK_SET(s4_clk,          plla_clk,  1, 1);
92 SH_FIXED_RATIO_CLK_SET(b_clk,           plla_clk,  1, 1);
93 SH_FIXED_RATIO_CLK_SET(out_clk,         plla_clk,  1, 1);
94 SH_FIXED_RATIO_CLK_SET(p_clk,           plla_clk,  1, 1);
95 SH_FIXED_RATIO_CLK_SET(g_clk,           plla_clk,  1, 1);
96 SH_FIXED_RATIO_CLK_SET(z_clk,           pllb_clk,  1, 1);
97
98 static struct clk *main_clks[] = {
99         &extal_clk,
100         &plla_clk,
101         &pllb_clk,
102         &i_clk,
103         &s_clk,
104         &s1_clk,
105         &s3_clk,
106         &s4_clk,
107         &b_clk,
108         &out_clk,
109         &p_clk,
110         &g_clk,
111         &z_clk,
112         &audio_clk_a,
113         &audio_clk_b,
114         &audio_clk_c,
115 };
116
117 enum {
118         MSTP331,
119         MSTP323, MSTP322, MSTP321,
120         MSTP311, MSTP310,
121         MSTP309, MSTP308, MSTP307,
122         MSTP114,
123         MSTP110, MSTP109,
124         MSTP100,
125         MSTP030,
126         MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
127         MSTP016, MSTP015, MSTP012, MSTP011, MSTP010,
128         MSTP009, MSTP008, MSTP007,
129         MSTP_NR };
130
131 static struct clk mstp_clks[MSTP_NR] = {
132         [MSTP331] = SH_CLK_MSTP32(&s4_clk, MSTPCR3, 31, 0), /* MMC */
133         [MSTP323] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 23, 0), /* SDHI0 */
134         [MSTP322] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 22, 0), /* SDHI1 */
135         [MSTP321] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 21, 0), /* SDHI2 */
136         [MSTP311] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 11, 0), /* SSI4 */
137         [MSTP310] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 10, 0), /* SSI5 */
138         [MSTP309] = SH_CLK_MSTP32(&p_clk, MSTPCR3,  9, 0), /* SSI6 */
139         [MSTP308] = SH_CLK_MSTP32(&p_clk, MSTPCR3,  8, 0), /* SSI7 */
140         [MSTP307] = SH_CLK_MSTP32(&p_clk, MSTPCR3,  7, 0), /* SSI8 */
141         [MSTP114] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 14, 0), /* Ether */
142         [MSTP110] = SH_CLK_MSTP32(&s_clk, MSTPCR1, 10, 0), /* VIN0 */
143         [MSTP109] = SH_CLK_MSTP32(&s_clk, MSTPCR1,  9, 0), /* VIN1 */
144         [MSTP100] = SH_CLK_MSTP32(&p_clk, MSTPCR1,  0, 0), /* USB0/1 */
145         [MSTP030] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 30, 0), /* I2C0 */
146         [MSTP029] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 29, 0), /* I2C1 */
147         [MSTP028] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 28, 0), /* I2C2 */
148         [MSTP027] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 27, 0), /* I2C3 */
149         [MSTP026] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 26, 0), /* SCIF0 */
150         [MSTP025] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 25, 0), /* SCIF1 */
151         [MSTP024] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 24, 0), /* SCIF2 */
152         [MSTP023] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 23, 0), /* SCIF3 */
153         [MSTP022] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 22, 0), /* SCIF4 */
154         [MSTP021] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 21, 0), /* SCIF5 */
155         [MSTP016] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 16, 0), /* TMU0 */
156         [MSTP015] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 15, 0), /* TMU1 */
157         [MSTP012] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 12, 0), /* SSI0 */
158         [MSTP011] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 11, 0), /* SSI1 */
159         [MSTP010] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 10, 0), /* SSI2 */
160         [MSTP009] = SH_CLK_MSTP32(&p_clk, MSTPCR0,  9, 0), /* SSI3 */
161         [MSTP008] = SH_CLK_MSTP32(&p_clk, MSTPCR0,  8, 0), /* SRU */
162         [MSTP007] = SH_CLK_MSTP32(&p_clk, MSTPCR0,  7, 0), /* HSPI */
163 };
164
165 static struct clk_lookup lookups[] = {
166         /* main */
167         CLKDEV_CON_ID("audio_clk_a",    &audio_clk_a),
168         CLKDEV_CON_ID("audio_clk_b",    &audio_clk_b),
169         CLKDEV_CON_ID("audio_clk_c",    &audio_clk_c),
170         CLKDEV_CON_ID("audio_clk_internal",     &s1_clk),
171         CLKDEV_CON_ID("shyway_clk",     &s_clk),
172         CLKDEV_CON_ID("peripheral_clk", &p_clk),
173
174         /* MSTP32 clocks */
175         CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP331]), /* MMC */
176         CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP323]), /* SDHI0 */
177         CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
178         CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
179         CLKDEV_DEV_ID("r8a777x-ether", &mstp_clks[MSTP114]), /* Ether */
180         CLKDEV_DEV_ID("r8a7778-vin.0", &mstp_clks[MSTP110]), /* VIN0 */
181         CLKDEV_DEV_ID("r8a7778-vin.1", &mstp_clks[MSTP109]), /* VIN1 */
182         CLKDEV_DEV_ID("ehci-platform", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */
183         CLKDEV_DEV_ID("ohci-platform", &mstp_clks[MSTP100]), /* USB OHCI port0/1 */
184         CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP100]), /* USB FUNC */
185         CLKDEV_DEV_ID("i2c-rcar.0", &mstp_clks[MSTP030]), /* I2C0 */
186         CLKDEV_DEV_ID("i2c-rcar.1", &mstp_clks[MSTP029]), /* I2C1 */
187         CLKDEV_DEV_ID("i2c-rcar.2", &mstp_clks[MSTP028]), /* I2C2 */
188         CLKDEV_DEV_ID("i2c-rcar.3", &mstp_clks[MSTP027]), /* I2C3 */
189         CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
190         CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
191         CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */
192         CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP023]), /* SCIF3 */
193         CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP022]), /* SCIF4 */
194         CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP021]), /* SCIF6 */
195         CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP016]), /* TMU00 */
196         CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP015]), /* TMU01 */
197         CLKDEV_DEV_ID("sh-hspi.0", &mstp_clks[MSTP007]), /* HSPI0 */
198         CLKDEV_DEV_ID("sh-hspi.1", &mstp_clks[MSTP007]), /* HSPI1 */
199         CLKDEV_DEV_ID("sh-hspi.2", &mstp_clks[MSTP007]), /* HSPI2 */
200         CLKDEV_DEV_ID("rcar_sound", &mstp_clks[MSTP008]), /* SRU */
201
202         CLKDEV_ICK_ID("ssi.0", "rcar_sound", &mstp_clks[MSTP012]),
203         CLKDEV_ICK_ID("ssi.1", "rcar_sound", &mstp_clks[MSTP011]),
204         CLKDEV_ICK_ID("ssi.2", "rcar_sound", &mstp_clks[MSTP010]),
205         CLKDEV_ICK_ID("ssi.3", "rcar_sound", &mstp_clks[MSTP009]),
206         CLKDEV_ICK_ID("ssi.4", "rcar_sound", &mstp_clks[MSTP311]),
207         CLKDEV_ICK_ID("ssi.5", "rcar_sound", &mstp_clks[MSTP310]),
208         CLKDEV_ICK_ID("ssi.6", "rcar_sound", &mstp_clks[MSTP309]),
209         CLKDEV_ICK_ID("ssi.7", "rcar_sound", &mstp_clks[MSTP308]),
210         CLKDEV_ICK_ID("ssi.8", "rcar_sound", &mstp_clks[MSTP307]),
211 };
212
213 void __init r8a7778_clock_init(void)
214 {
215         void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
216         u32 mode;
217         int k, ret = 0;
218
219         BUG_ON(!modemr);
220         mode = ioread32(modemr);
221         iounmap(modemr);
222
223         switch (mode & (MD(19) | MD(18) | MD(12) | MD(11))) {
224         case MD(19):
225                 extal_clk.rate = 38000000;
226                 SH_CLK_SET_RATIO(&plla_clk_ratio,       21, 1);
227                 SH_CLK_SET_RATIO(&pllb_clk_ratio,       21, 1);
228                 break;
229         case MD(19) | MD(11):
230                 extal_clk.rate = 33333333;
231                 SH_CLK_SET_RATIO(&plla_clk_ratio,       24, 1);
232                 SH_CLK_SET_RATIO(&pllb_clk_ratio,       24, 1);
233                 break;
234         case MD(19) | MD(12):
235                 extal_clk.rate = 28500000;
236                 SH_CLK_SET_RATIO(&plla_clk_ratio,       28, 1);
237                 SH_CLK_SET_RATIO(&pllb_clk_ratio,       28, 1);
238                 break;
239         case MD(19) | MD(12) | MD(11):
240                 extal_clk.rate = 25000000;
241                 SH_CLK_SET_RATIO(&plla_clk_ratio,       32, 1);
242                 SH_CLK_SET_RATIO(&pllb_clk_ratio,       32, 1);
243                 break;
244         case MD(19) | MD(18) | MD(11):
245                 extal_clk.rate = 33333333;
246                 SH_CLK_SET_RATIO(&plla_clk_ratio,       24, 1);
247                 SH_CLK_SET_RATIO(&pllb_clk_ratio,       21, 1);
248                 break;
249         case MD(19) | MD(18) | MD(12):
250                 extal_clk.rate = 28500000;
251                 SH_CLK_SET_RATIO(&plla_clk_ratio,       28, 1);
252                 SH_CLK_SET_RATIO(&pllb_clk_ratio,       21, 1);
253                 break;
254         case MD(19) | MD(18) | MD(12) | MD(11):
255                 extal_clk.rate = 25000000;
256                 SH_CLK_SET_RATIO(&plla_clk_ratio,       32, 1);
257                 SH_CLK_SET_RATIO(&pllb_clk_ratio,       24, 1);
258                 break;
259         default:
260                 BUG();
261         }
262
263         if (mode & MD(1)) {
264                 SH_CLK_SET_RATIO(&i_clk_ratio,  1, 1);
265                 SH_CLK_SET_RATIO(&s_clk_ratio,  1, 3);
266                 SH_CLK_SET_RATIO(&s1_clk_ratio, 1, 6);
267                 SH_CLK_SET_RATIO(&s3_clk_ratio, 1, 4);
268                 SH_CLK_SET_RATIO(&s4_clk_ratio, 1, 8);
269                 SH_CLK_SET_RATIO(&p_clk_ratio,  1, 12);
270                 SH_CLK_SET_RATIO(&g_clk_ratio,  1, 12);
271                 if (mode & MD(2)) {
272                         SH_CLK_SET_RATIO(&b_clk_ratio,          1, 18);
273                         SH_CLK_SET_RATIO(&out_clk_ratio,        1, 18);
274                 } else {
275                         SH_CLK_SET_RATIO(&b_clk_ratio,          1, 12);
276                         SH_CLK_SET_RATIO(&out_clk_ratio,        1, 12);
277                 }
278         } else {
279                 SH_CLK_SET_RATIO(&i_clk_ratio,  1, 1);
280                 SH_CLK_SET_RATIO(&s_clk_ratio,  1, 4);
281                 SH_CLK_SET_RATIO(&s1_clk_ratio, 1, 8);
282                 SH_CLK_SET_RATIO(&s3_clk_ratio, 1, 4);
283                 SH_CLK_SET_RATIO(&s4_clk_ratio, 1, 8);
284                 SH_CLK_SET_RATIO(&p_clk_ratio,  1, 16);
285                 SH_CLK_SET_RATIO(&g_clk_ratio,  1, 12);
286                 if (mode & MD(2)) {
287                         SH_CLK_SET_RATIO(&b_clk_ratio,          1, 16);
288                         SH_CLK_SET_RATIO(&out_clk_ratio,        1, 16);
289                 } else {
290                         SH_CLK_SET_RATIO(&b_clk_ratio,          1, 12);
291                         SH_CLK_SET_RATIO(&out_clk_ratio,        1, 12);
292                 }
293         }
294
295         for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
296                 ret = clk_register(main_clks[k]);
297
298         if (!ret)
299                 ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
300
301         clkdev_add_table(lookups, ARRAY_SIZE(lookups));
302
303         if (!ret)
304                 shmobile_clk_init();
305         else
306                 panic("failed to setup r8a7778 clocks\n");
307 }