]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/mips/mediatek/mtk_soc.c
Revis manual pages. [SA-18:08.tcp]
[FreeBSD/FreeBSD.git] / sys / mips / mediatek / mtk_soc.c
1 /*-
2  * Copyright (c) 2016 Stanislav Galabov.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/bus.h>
33 #include <sys/kernel.h>
34 #include <sys/module.h>
35 #include <sys/rman.h>
36
37 #include <machine/fdt.h>
38
39 #include <dev/ofw/openfirm.h>
40 #include <dev/ofw/ofw_bus.h>
41 #include <dev/ofw/ofw_bus_subr.h>
42
43 #include <dev/fdt/fdt_common.h>
44 #include <dev/fdt/fdt_clock.h>
45
46 #include <mips/mediatek/fdt_reset.h>
47 #include <mips/mediatek/mtk_sysctl.h>
48 #include <mips/mediatek/mtk_soc.h>
49
50 static uint32_t mtk_soc_socid = MTK_SOC_UNKNOWN;
51 static uint32_t mtk_soc_uartclk = 0;
52 static uint32_t mtk_soc_cpuclk = MTK_CPU_CLK_880MHZ;
53 static uint32_t mtk_soc_timerclk = MTK_CPU_CLK_880MHZ / 2;
54
55 static const struct ofw_compat_data compat_data[] = {
56         { "ralink,rt3050-soc",          MTK_SOC_RT3050 },
57         { "ralink,rt3052-soc",          MTK_SOC_RT3052 },
58         { "ralink,rt3350-soc",          MTK_SOC_RT3350 },
59         { "ralink,rt3352-soc",          MTK_SOC_RT3352 },
60         { "ralink,rt3662-soc",          MTK_SOC_RT3662 },
61         { "ralink,rt3883-soc",          MTK_SOC_RT3883 },
62         { "ralink,rt5350-soc",          MTK_SOC_RT5350 },
63         { "ralink,mtk7620a-soc",        MTK_SOC_MT7620A },
64         { "ralink,mt7620a-soc",         MTK_SOC_MT7620A },
65         { "ralink,mtk7620n-soc",        MTK_SOC_MT7620N },
66         { "ralink,mt7620n-soc",         MTK_SOC_MT7620N },
67         { "mediatek,mtk7621-soc",       MTK_SOC_MT7621 },
68         { "mediatek,mt7621-soc",        MTK_SOC_MT7621 },
69         { "ralink,mt7621-soc",          MTK_SOC_MT7621 },
70         { "ralink,mtk7621-soc",         MTK_SOC_MT7621 },
71         { "ralink,mtk7628an-soc",       MTK_SOC_MT7628 },
72         { "mediatek,mt7628an-soc",      MTK_SOC_MT7628 },
73         { "ralink,mtk7688-soc",         MTK_SOC_MT7688 },
74
75         /* Sentinel */
76         { NULL,                         MTK_SOC_UNKNOWN },
77 };
78
79 static uint32_t
80 mtk_detect_cpuclk_rt305x(bus_space_tag_t bst, bus_space_handle_t bsh)
81 {
82         uint32_t val;
83
84         val = bus_space_read_4(bst, bsh, SYSCTL_CHIPID0_3);
85         if (val == RT3350_CHIPID0_3)
86                 return (MTK_CPU_CLK_320MHZ);
87
88         val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
89         val >>= RT305X_CPU_CLKSEL_OFF;
90         val &= RT305X_CPU_CLKSEL_MSK;
91
92         return ((val == 0) ? MTK_CPU_CLK_320MHZ : MTK_CPU_CLK_384MHZ);
93 }
94
95 static uint32_t
96 mtk_detect_cpuclk_rt3352(bus_space_tag_t bst, bus_space_handle_t bsh)
97 {
98         uint32_t val;
99
100         val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
101         val >>= RT3352_CPU_CLKSEL_OFF;
102         val &= RT3352_CPU_CLKSEL_MSK;
103
104         if (val)
105                 return (MTK_CPU_CLK_400MHZ);
106
107         return (MTK_CPU_CLK_384MHZ);
108 }
109
110 static uint32_t
111 mtk_detect_cpuclk_rt3883(bus_space_tag_t bst, bus_space_handle_t bsh)
112 {
113         uint32_t val;
114
115         val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
116         val >>= RT3883_CPU_CLKSEL_OFF;
117         val &= RT3883_CPU_CLKSEL_MSK;
118
119         switch (val) {
120         case 0:
121                 return (MTK_CPU_CLK_250MHZ);
122         case 1:
123                 return (MTK_CPU_CLK_384MHZ);
124         case 2:
125                 return (MTK_CPU_CLK_480MHZ);
126         case 3:
127                 return (MTK_CPU_CLK_500MHZ);
128         }
129
130         /* Never reached */
131         return (0);
132 }
133
134 static uint32_t
135 mtk_detect_cpuclk_rt5350(bus_space_tag_t bst, bus_space_handle_t bsh)
136 {
137         uint32_t val1, val2;
138
139         val1 = val2 = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
140
141         val1 >>= RT5350_CPU_CLKSEL_OFF1;
142         val2 >>= RT5350_CPU_CLKSEL_OFF2;
143         val1 &= RT5350_CPU_CLKSEL_MSK;
144         val2 &= RT5350_CPU_CLKSEL_MSK;
145         val1 |= (val2 << 1);
146
147         switch (val1) {
148         case 0:
149                 return (MTK_CPU_CLK_360MHZ);
150         case 1:
151                 /* Reserved value, but we return UNKNOWN */
152                 return (MTK_CPU_CLK_UNKNOWN);
153         case 2:
154                 return (MTK_CPU_CLK_320MHZ);
155         case 3:
156                 return (MTK_CPU_CLK_300MHZ);
157         }
158
159         /* Never reached */
160         return (0);
161 }
162
163 static uint32_t
164 mtk_detect_cpuclk_mt7620(bus_space_tag_t bst, bus_space_handle_t bsh)
165 {
166         uint32_t val, mul, div, res;
167
168         val = bus_space_read_4(bst, bsh, SYSCTL_MT7620_CPLL_CFG1);
169         if (val & MT7620_CPU_CLK_AUX0)
170                 return (MTK_CPU_CLK_480MHZ);
171
172         val = bus_space_read_4(bst, bsh, SYSCTL_MT7620_CPLL_CFG0);
173         if (!(val & MT7620_CPLL_SW_CFG))
174                 return (MTK_CPU_CLK_600MHZ);
175
176         mul = MT7620_PLL_MULT_RATIO_BASE + ((val >> MT7620_PLL_MULT_RATIO_OFF) &
177             MT7620_PLL_MULT_RATIO_MSK);
178         div = (val >> MT7620_PLL_DIV_RATIO_OFF) & MT7620_PLL_DIV_RATIO_MSK;
179
180         if (div != MT7620_PLL_DIV_RATIO_MSK)
181                 div += MT7620_PLL_DIV_RATIO_BASE;
182         else
183                 div = MT7620_PLL_DIV_RATIO_MAX;
184
185         res = (MT7620_XTAL_40 * mul) / div;
186
187         return (MTK_MHZ(res));
188 }
189
190 static uint32_t
191 mtk_detect_cpuclk_mt7621(bus_space_tag_t bst, bus_space_handle_t bsh)
192 {
193         uint32_t val, div, res;
194
195         val = bus_space_read_4(bst, bsh, SYSCTL_CLKCFG0);
196         if (val & MT7621_USES_MEMDIV) {
197                 div = bus_space_read_4(bst, bsh, MTK_MT7621_CLKDIV_REG);
198                 div >>= MT7621_MEMDIV_OFF;
199                 div &= MT7621_MEMDIV_MSK;
200                 div += MT7621_MEMDIV_BASE;
201
202                 val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
203                 val >>= MT7621_CLKSEL_OFF;
204                 val &= MT7621_CLKSEL_MSK;
205
206                 if (val >= MT7621_CLKSEL_25MHZ_VAL)
207                         res = div * MT7621_CLKSEL_25MHZ;
208                 else if (val >= MT7621_CLKSEL_20MHZ_VAL)
209                         res = div * MT7621_CLKSEL_20MHZ;
210                 else
211                         res = div * 0; /* XXX: not sure about this */
212         } else {
213                 val = bus_space_read_4(bst, bsh, SYSCTL_CUR_CLK_STS);
214                 div = (val >> MT7621_CLK_STS_DIV_OFF) & MT7621_CLK_STS_MSK;
215                 val &= MT7621_CLK_STS_MSK;
216
217                 res = (MT7621_CLK_STS_BASE * val) / div;
218         }
219
220         return (MTK_MHZ(res));
221 }
222
223 static uint32_t
224 mtk_detect_cpuclk_mt7628(bus_space_tag_t bst, bus_space_handle_t bsh)
225 {
226         uint32_t val;
227
228         val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
229         val >>= MT7628_CPU_CLKSEL_OFF;
230         val &= MT7628_CPU_CLKSEL_MSK;
231
232         if (val)
233                 return (MTK_CPU_CLK_580MHZ);
234
235         return (MTK_CPU_CLK_575MHZ);
236 }
237
238 void
239 mtk_soc_try_early_detect(void)
240 {
241         bus_space_tag_t bst;
242         bus_space_handle_t bsh;
243         uint32_t base;
244         phandle_t node;
245         int i;
246
247         if ((node = OF_finddevice("/")) == -1)
248                 return;
249
250         for (i = 0; compat_data[i].ocd_str != NULL; i++) {
251                 if (fdt_is_compatible(node, compat_data[i].ocd_str)) {
252                         mtk_soc_socid = compat_data[i].ocd_data;
253                         break;
254                 }
255         }
256
257         if (mtk_soc_socid == MTK_SOC_UNKNOWN) {
258                 /* We don't know the SoC, so we don't know how to get clocks */
259                 return;
260         }
261
262         bst = fdtbus_bs_tag;
263         if (mtk_soc_socid == MTK_SOC_MT7621)
264                 base = MTK_MT7621_BASE;
265         else
266                 base = MTK_DEFAULT_BASE;
267
268         if (bus_space_map(bst, base, MTK_DEFAULT_SIZE, 0, &bsh))
269                 return;
270
271         /* First, figure out the CPU clock */
272         switch (mtk_soc_socid) {
273         case MTK_SOC_RT3050:  /* fallthrough */
274         case MTK_SOC_RT3052:
275         case MTK_SOC_RT3350:
276                 mtk_soc_cpuclk = mtk_detect_cpuclk_rt305x(bst, bsh);
277                 break;
278         case MTK_SOC_RT3352:
279                 mtk_soc_cpuclk = mtk_detect_cpuclk_rt3352(bst, bsh);
280                 break;
281         case MTK_SOC_RT3662:  /* fallthrough */
282         case MTK_SOC_RT3883:
283                 mtk_soc_cpuclk = mtk_detect_cpuclk_rt3883(bst, bsh);
284                 break;
285         case MTK_SOC_RT5350:
286                 mtk_soc_cpuclk = mtk_detect_cpuclk_rt5350(bst, bsh);
287                 break;
288         case MTK_SOC_MT7620A: /* fallthrough */
289         case MTK_SOC_MT7620N:
290                 mtk_soc_cpuclk = mtk_detect_cpuclk_mt7620(bst, bsh);
291                 break;
292         case MTK_SOC_MT7621:
293                 mtk_soc_cpuclk = mtk_detect_cpuclk_mt7621(bst, bsh);
294                 break;
295         case MTK_SOC_MT7628:  /* fallthrough */
296         case MTK_SOC_MT7688:
297                 mtk_soc_cpuclk = mtk_detect_cpuclk_mt7628(bst, bsh);
298                 break;
299         default:
300                 /* We don't know the SoC, so we can't find the CPU clock */
301                 break;
302         }
303
304         /* Now figure out the timer clock */
305         if (mtk_soc_socid == MTK_SOC_MT7621) {
306 #ifdef notyet
307                 /* 
308                  * We use the GIC timer for timing source and its clock freq is
309                  * the same as the CPU's clock freq
310                  */
311                 mtk_soc_timerclk = mtk_soc_cpuclk;
312 #else
313                 /*
314                  * When GIC timer and MIPS timer are ready to co-exist and
315                  * GIC timer is actually implemented, we need to switch to it.
316                  * Until then we use a fake GIC timer, which is actually a
317                  * normal MIPS ticker, so the timer clock is half the CPU clock
318                  */
319                 mtk_soc_timerclk = mtk_soc_cpuclk / 2;
320 #endif
321         } else {
322                 /*
323                  * We use the MIPS ticker for the rest for now, so
324                  * the CPU clock is divided by 2
325                  */
326                 mtk_soc_timerclk = mtk_soc_cpuclk / 2;
327         }
328
329         switch (mtk_soc_socid) {
330         case MTK_SOC_RT3350:  /* fallthrough */
331         case MTK_SOC_RT3050:  /* fallthrough */
332         case MTK_SOC_RT3052:
333                 /* UART clock is CPU clock / 3 */
334                 mtk_soc_uartclk = mtk_soc_cpuclk / MTK_UARTDIV_3;
335                 break;
336         case MTK_SOC_RT3352:  /* fallthrough */
337         case MTK_SOC_RT3662:  /* fallthrough */
338         case MTK_SOC_RT3883:  /* fallthrough */
339         case MTK_SOC_RT5350:  /* fallthrough */
340         case MTK_SOC_MT7620A: /* fallthrough */
341         case MTK_SOC_MT7620N: /* fallthrough */
342         case MTK_SOC_MT7628:  /* fallthrough */
343         case MTK_SOC_MT7688:
344                 /* UART clock is always 40MHz */
345                 mtk_soc_uartclk = MTK_UART_CLK_40MHZ;
346                 break;
347         case MTK_SOC_MT7621:
348                 /* UART clock is always 50MHz */
349                 mtk_soc_uartclk = MTK_UART_CLK_50MHZ;
350                 break;
351         default:
352                 /* We don't know the SoC, so we don't know the UART clock */
353                 break;
354         }
355
356         bus_space_unmap(bst, bsh, MTK_DEFAULT_SIZE);
357 }
358
359 uint32_t
360 mtk_soc_get_uartclk(void)
361 {
362
363         return mtk_soc_uartclk;
364 }
365
366 uint32_t
367 mtk_soc_get_cpuclk(void)
368 {
369
370         return mtk_soc_cpuclk;
371 }
372
373 uint32_t
374 mtk_soc_get_timerclk(void)
375 {
376
377         return mtk_soc_timerclk;
378 }
379
380 uint32_t
381 mtk_soc_get_socid(void)
382 {
383
384         return mtk_soc_socid;
385 }
386
387 /*
388  * The following are generic reset and clock functions
389  */
390
391 /* Default reset time is 100ms */
392 #define DEFAULT_RESET_TIME      100000
393
394 int
395 mtk_soc_reset_device(device_t dev)
396 {
397         int res;
398
399         res = fdt_reset_assert_all(dev);
400         if (res == 0) {
401                 DELAY(DEFAULT_RESET_TIME);
402                 res = fdt_reset_deassert_all(dev);
403                 if (res == 0)
404                         DELAY(DEFAULT_RESET_TIME);
405         }
406
407         return (res);
408 }
409
410 int
411 mtk_soc_stop_clock(device_t dev)
412 {
413
414         return (fdt_clock_disable_all(dev));
415 }
416
417 int
418 mtk_soc_start_clock(device_t dev)
419 {
420
421         return (fdt_clock_enable_all(dev));
422 }
423
424 int
425 mtk_soc_assert_reset(device_t dev)
426 {
427
428         return (fdt_reset_assert_all(dev));
429 }
430
431 int
432 mtk_soc_deassert_reset(device_t dev)
433 {
434
435         return (fdt_reset_deassert_all(dev));
436 }
437
438 void
439 mtk_soc_reset(void)
440 {
441
442         mtk_sysctl_clr_set(SYSCTL_RSTCTRL, 0, 1);
443         mtk_sysctl_clr_set(SYSCTL_RSTCTRL, 1, 0);
444 }