]> Pileus Git - ~andy/linux/blob - arch/arm/mach-shmobile/clock-r8a7778.c
ARM: smp_on_up: move inline asm ALT_SMP patching macro out of spinlock.h
[~andy/linux] / 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 /*
73  * clock ratio of these clock will be updated
74  * on r8a7778_clock_init()
75  */
76 SH_FIXED_RATIO_CLK_SET(plla_clk,        extal_clk, 1, 1);
77 SH_FIXED_RATIO_CLK_SET(pllb_clk,        extal_clk, 1, 1);
78 SH_FIXED_RATIO_CLK_SET(i_clk,           plla_clk,  1, 1);
79 SH_FIXED_RATIO_CLK_SET(s_clk,           plla_clk,  1, 1);
80 SH_FIXED_RATIO_CLK_SET(s1_clk,          plla_clk,  1, 1);
81 SH_FIXED_RATIO_CLK_SET(s3_clk,          plla_clk,  1, 1);
82 SH_FIXED_RATIO_CLK_SET(s4_clk,          plla_clk,  1, 1);
83 SH_FIXED_RATIO_CLK_SET(b_clk,           plla_clk,  1, 1);
84 SH_FIXED_RATIO_CLK_SET(out_clk,         plla_clk,  1, 1);
85 SH_FIXED_RATIO_CLK_SET(p_clk,           plla_clk,  1, 1);
86 SH_FIXED_RATIO_CLK_SET(g_clk,           plla_clk,  1, 1);
87 SH_FIXED_RATIO_CLK_SET(z_clk,           pllb_clk,  1, 1);
88
89 static struct clk *main_clks[] = {
90         &extal_clk,
91         &plla_clk,
92         &pllb_clk,
93         &i_clk,
94         &s_clk,
95         &s1_clk,
96         &s3_clk,
97         &s4_clk,
98         &b_clk,
99         &out_clk,
100         &p_clk,
101         &g_clk,
102         &z_clk,
103 };
104
105 enum {
106         MSTP331,
107         MSTP323, MSTP322, MSTP321,
108         MSTP114,
109         MSTP110, MSTP109,
110         MSTP100,
111         MSTP030,
112         MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
113         MSTP016, MSTP015,
114         MSTP007,
115         MSTP_NR };
116
117 static struct clk mstp_clks[MSTP_NR] = {
118         [MSTP331] = SH_CLK_MSTP32(&s4_clk, MSTPCR3, 31, 0), /* MMC */
119         [MSTP323] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 23, 0), /* SDHI0 */
120         [MSTP322] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 22, 0), /* SDHI1 */
121         [MSTP321] = SH_CLK_MSTP32(&p_clk, MSTPCR3, 21, 0), /* SDHI2 */
122         [MSTP114] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 14, 0), /* Ether */
123         [MSTP110] = SH_CLK_MSTP32(&s_clk, MSTPCR1, 10, 0), /* VIN0 */
124         [MSTP109] = SH_CLK_MSTP32(&s_clk, MSTPCR1,  9, 0), /* VIN1 */
125         [MSTP100] = SH_CLK_MSTP32(&p_clk, MSTPCR1,  0, 0), /* USB0/1 */
126         [MSTP030] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 30, 0), /* I2C0 */
127         [MSTP029] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 29, 0), /* I2C1 */
128         [MSTP028] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 28, 0), /* I2C2 */
129         [MSTP027] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 27, 0), /* I2C3 */
130         [MSTP026] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 26, 0), /* SCIF0 */
131         [MSTP025] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 25, 0), /* SCIF1 */
132         [MSTP024] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 24, 0), /* SCIF2 */
133         [MSTP023] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 23, 0), /* SCIF3 */
134         [MSTP022] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 22, 0), /* SCIF4 */
135         [MSTP021] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 21, 0), /* SCIF5 */
136         [MSTP016] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 16, 0), /* TMU0 */
137         [MSTP015] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 15, 0), /* TMU1 */
138         [MSTP007] = SH_CLK_MSTP32(&p_clk, MSTPCR0,  7, 0), /* HSPI */
139 };
140
141 static struct clk_lookup lookups[] = {
142         /* main */
143         CLKDEV_CON_ID("shyway_clk",     &s_clk),
144         CLKDEV_CON_ID("peripheral_clk", &p_clk),
145
146         /* MSTP32 clocks */
147         CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP331]), /* MMC */
148         CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP323]), /* SDHI0 */
149         CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
150         CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
151         CLKDEV_DEV_ID("r8a777x-ether", &mstp_clks[MSTP114]), /* Ether */
152         CLKDEV_DEV_ID("r8a7778-vin.0", &mstp_clks[MSTP110]), /* VIN0 */
153         CLKDEV_DEV_ID("r8a7778-vin.1", &mstp_clks[MSTP109]), /* VIN1 */
154         CLKDEV_DEV_ID("ehci-platform", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */
155         CLKDEV_DEV_ID("ohci-platform", &mstp_clks[MSTP100]), /* USB OHCI port0/1 */
156         CLKDEV_DEV_ID("i2c-rcar.0", &mstp_clks[MSTP030]), /* I2C0 */
157         CLKDEV_DEV_ID("i2c-rcar.1", &mstp_clks[MSTP029]), /* I2C1 */
158         CLKDEV_DEV_ID("i2c-rcar.2", &mstp_clks[MSTP028]), /* I2C2 */
159         CLKDEV_DEV_ID("i2c-rcar.3", &mstp_clks[MSTP027]), /* I2C3 */
160         CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP026]), /* SCIF0 */
161         CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP025]), /* SCIF1 */
162         CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP024]), /* SCIF2 */
163         CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP023]), /* SCIF3 */
164         CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP022]), /* SCIF4 */
165         CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP021]), /* SCIF6 */
166         CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP016]), /* TMU00 */
167         CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP015]), /* TMU01 */
168         CLKDEV_DEV_ID("sh-hspi.0", &mstp_clks[MSTP007]), /* HSPI0 */
169         CLKDEV_DEV_ID("sh-hspi.1", &mstp_clks[MSTP007]), /* HSPI1 */
170         CLKDEV_DEV_ID("sh-hspi.2", &mstp_clks[MSTP007]), /* HSPI2 */
171 };
172
173 void __init r8a7778_clock_init(void)
174 {
175         void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
176         u32 mode;
177         int k, ret = 0;
178
179         BUG_ON(!modemr);
180         mode = ioread32(modemr);
181         iounmap(modemr);
182
183         switch (mode & (MD(19) | MD(18) | MD(12) | MD(11))) {
184         case MD(19):
185                 extal_clk.rate = 38000000;
186                 SH_CLK_SET_RATIO(&plla_clk_ratio,       21, 1);
187                 SH_CLK_SET_RATIO(&pllb_clk_ratio,       21, 1);
188                 break;
189         case MD(19) | MD(11):
190                 extal_clk.rate = 33333333;
191                 SH_CLK_SET_RATIO(&plla_clk_ratio,       24, 1);
192                 SH_CLK_SET_RATIO(&pllb_clk_ratio,       24, 1);
193                 break;
194         case MD(19) | MD(12):
195                 extal_clk.rate = 28500000;
196                 SH_CLK_SET_RATIO(&plla_clk_ratio,       28, 1);
197                 SH_CLK_SET_RATIO(&pllb_clk_ratio,       28, 1);
198                 break;
199         case MD(19) | MD(12) | MD(11):
200                 extal_clk.rate = 25000000;
201                 SH_CLK_SET_RATIO(&plla_clk_ratio,       32, 1);
202                 SH_CLK_SET_RATIO(&pllb_clk_ratio,       32, 1);
203                 break;
204         case MD(19) | MD(18) | MD(11):
205                 extal_clk.rate = 33333333;
206                 SH_CLK_SET_RATIO(&plla_clk_ratio,       24, 1);
207                 SH_CLK_SET_RATIO(&pllb_clk_ratio,       21, 1);
208                 break;
209         case MD(19) | MD(18) | MD(12):
210                 extal_clk.rate = 28500000;
211                 SH_CLK_SET_RATIO(&plla_clk_ratio,       28, 1);
212                 SH_CLK_SET_RATIO(&pllb_clk_ratio,       21, 1);
213                 break;
214         case MD(19) | MD(18) | MD(12) | MD(11):
215                 extal_clk.rate = 25000000;
216                 SH_CLK_SET_RATIO(&plla_clk_ratio,       32, 1);
217                 SH_CLK_SET_RATIO(&pllb_clk_ratio,       24, 1);
218                 break;
219         default:
220                 BUG();
221         }
222
223         if (mode & MD(1)) {
224                 SH_CLK_SET_RATIO(&i_clk_ratio,  1, 1);
225                 SH_CLK_SET_RATIO(&s_clk_ratio,  1, 3);
226                 SH_CLK_SET_RATIO(&s1_clk_ratio, 1, 6);
227                 SH_CLK_SET_RATIO(&s3_clk_ratio, 1, 4);
228                 SH_CLK_SET_RATIO(&s4_clk_ratio, 1, 8);
229                 SH_CLK_SET_RATIO(&p_clk_ratio,  1, 12);
230                 SH_CLK_SET_RATIO(&g_clk_ratio,  1, 12);
231                 if (mode & MD(2)) {
232                         SH_CLK_SET_RATIO(&b_clk_ratio,          1, 18);
233                         SH_CLK_SET_RATIO(&out_clk_ratio,        1, 18);
234                 } else {
235                         SH_CLK_SET_RATIO(&b_clk_ratio,          1, 12);
236                         SH_CLK_SET_RATIO(&out_clk_ratio,        1, 12);
237                 }
238         } else {
239                 SH_CLK_SET_RATIO(&i_clk_ratio,  1, 1);
240                 SH_CLK_SET_RATIO(&s_clk_ratio,  1, 4);
241                 SH_CLK_SET_RATIO(&s1_clk_ratio, 1, 8);
242                 SH_CLK_SET_RATIO(&s3_clk_ratio, 1, 4);
243                 SH_CLK_SET_RATIO(&s4_clk_ratio, 1, 8);
244                 SH_CLK_SET_RATIO(&p_clk_ratio,  1, 16);
245                 SH_CLK_SET_RATIO(&g_clk_ratio,  1, 12);
246                 if (mode & MD(2)) {
247                         SH_CLK_SET_RATIO(&b_clk_ratio,          1, 16);
248                         SH_CLK_SET_RATIO(&out_clk_ratio,        1, 16);
249                 } else {
250                         SH_CLK_SET_RATIO(&b_clk_ratio,          1, 12);
251                         SH_CLK_SET_RATIO(&out_clk_ratio,        1, 12);
252                 }
253         }
254
255         for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
256                 ret = clk_register(main_clks[k]);
257
258         if (!ret)
259                 ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
260
261         clkdev_add_table(lookups, ARRAY_SIZE(lookups));
262
263         if (!ret)
264                 shmobile_clk_init();
265         else
266                 panic("failed to setup r8a7778 clocks\n");
267 }