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
50static uint32_t mtk_soc_socid = MTK_SOC_UNKNOWN;
51static uint32_t mtk_soc_uartclk = 0;
52static uint32_t mtk_soc_cpuclk = MTK_CPU_CLK_880MHZ;
53static uint32_t mtk_soc_timerclk = MTK_CPU_CLK_880MHZ / 2;
54
55static const struct ofw_compat_data compat_data[] = {
56	{ "ralink,rt2880-soc",		MTK_SOC_RT2880 },
57	{ "ralink,rt3050-soc",		MTK_SOC_RT3050 },
58	{ "ralink,rt3052-soc",		MTK_SOC_RT3052 },
59	{ "ralink,rt3350-soc",		MTK_SOC_RT3350 },
60	{ "ralink,rt3352-soc",		MTK_SOC_RT3352 },
61	{ "ralink,rt3662-soc",		MTK_SOC_RT3662 },
62	{ "ralink,rt3883-soc",		MTK_SOC_RT3883 },
63	{ "ralink,rt5350-soc",		MTK_SOC_RT5350 },
64	{ "ralink,mtk7620a-soc",	MTK_SOC_MT7620A },
65	{ "ralink,mt7620a-soc",		MTK_SOC_MT7620A },
66	{ "ralink,mtk7620n-soc",	MTK_SOC_MT7620N },
67	{ "ralink,mt7620n-soc",		MTK_SOC_MT7620N },
68	{ "mediatek,mtk7621-soc",	MTK_SOC_MT7621 },
69	{ "mediatek,mt7621-soc",	MTK_SOC_MT7621 },
70	{ "ralink,mt7621-soc",		MTK_SOC_MT7621 },
71	{ "ralink,mtk7621-soc",		MTK_SOC_MT7621 },
72	{ "ralink,mtk7628an-soc",	MTK_SOC_MT7628 },
73	{ "mediatek,mt7628an-soc",	MTK_SOC_MT7628 },
74	{ "ralink,mtk7688-soc",		MTK_SOC_MT7688 },
75
76	/* Sentinel */
77	{ NULL,				MTK_SOC_UNKNOWN },
78};
79
80static uint32_t
81mtk_detect_cpuclk_rt2880(bus_space_tag_t bst, bus_space_handle_t bsh)
82{
83	uint32_t val;
84
85	val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
86	val >>= RT2880_CPU_CLKSEL_OFF;
87	val &= RT2880_CPU_CLKSEL_MSK;
88
89	switch (val) {
90	case 0:
91		return (MTK_CPU_CLK_250MHZ);
92	case 1:
93		return (MTK_CPU_CLK_266MHZ);
94	case 2:
95		return (MTK_CPU_CLK_280MHZ);
96	case 3:
97		return (MTK_CPU_CLK_300MHZ);
98	}
99
100	/* Never reached */
101	return (0);
102}
103
104static uint32_t
105mtk_detect_cpuclk_rt305x(bus_space_tag_t bst, bus_space_handle_t bsh)
106{
107	uint32_t val;
108
109	val = bus_space_read_4(bst, bsh, SYSCTL_CHIPID0_3);
110	if (val == RT3350_CHIPID0_3)
111		return (MTK_CPU_CLK_320MHZ);
112
113	val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
114	val >>= RT305X_CPU_CLKSEL_OFF;
115	val &= RT305X_CPU_CLKSEL_MSK;
116
117	return ((val == 0) ? MTK_CPU_CLK_320MHZ : MTK_CPU_CLK_384MHZ);
118}
119
120static uint32_t
121mtk_detect_cpuclk_rt3352(bus_space_tag_t bst, bus_space_handle_t bsh)
122{
123	uint32_t val;
124
125	val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
126	val >>= RT3352_CPU_CLKSEL_OFF;
127	val &= RT3352_CPU_CLKSEL_MSK;
128
129	if (val)
130		return (MTK_CPU_CLK_400MHZ);
131
132	return (MTK_CPU_CLK_384MHZ);
133}
134
135static uint32_t
136mtk_detect_cpuclk_rt3883(bus_space_tag_t bst, bus_space_handle_t bsh)
137{
138	uint32_t val;
139
140	val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
141	val >>= RT3883_CPU_CLKSEL_OFF;
142	val &= RT3883_CPU_CLKSEL_MSK;
143
144	switch (val) {
145	case 0:
146		return (MTK_CPU_CLK_250MHZ);
147	case 1:
148		return (MTK_CPU_CLK_384MHZ);
149	case 2:
150		return (MTK_CPU_CLK_480MHZ);
151	case 3:
152		return (MTK_CPU_CLK_500MHZ);
153	}
154
155	/* Never reached */
156	return (0);
157}
158
159static uint32_t
160mtk_detect_cpuclk_rt5350(bus_space_tag_t bst, bus_space_handle_t bsh)
161{
162	uint32_t val1, val2;
163
164	val1 = val2 = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
165
166	val1 >>= RT5350_CPU_CLKSEL_OFF1;
167	val2 >>= RT5350_CPU_CLKSEL_OFF2;
168	val1 &= RT5350_CPU_CLKSEL_MSK;
169	val2 &= RT5350_CPU_CLKSEL_MSK;
170	val1 |= (val2 << 1);
171
172	switch (val1) {
173	case 0:
174		return (MTK_CPU_CLK_360MHZ);
175	case 1:
176		/* Reserved value, but we return UNKNOWN */
177		return (MTK_CPU_CLK_UNKNOWN);
178	case 2:
179		return (MTK_CPU_CLK_320MHZ);
180	case 3:
181		return (MTK_CPU_CLK_300MHZ);
182	}
183
184	/* Never reached */
185	return (0);
186}
187
188static uint32_t
189mtk_detect_cpuclk_mt7620(bus_space_tag_t bst, bus_space_handle_t bsh)
190{
191	uint32_t val, mul, div, res;
192
193	val = bus_space_read_4(bst, bsh, SYSCTL_MT7620_CPLL_CFG1);
194	if (val & MT7620_CPU_CLK_AUX0)
195		return (MTK_CPU_CLK_480MHZ);
196
197	val = bus_space_read_4(bst, bsh, SYSCTL_MT7620_CPLL_CFG0);
198	if (!(val & MT7620_CPLL_SW_CFG))
199		return (MTK_CPU_CLK_600MHZ);
200
201	mul = MT7620_PLL_MULT_RATIO_BASE + ((val >> MT7620_PLL_MULT_RATIO_OFF) &
202	    MT7620_PLL_MULT_RATIO_MSK);
203	div = (val >> MT7620_PLL_DIV_RATIO_OFF) & MT7620_PLL_DIV_RATIO_MSK;
204
205	if (div != MT7620_PLL_DIV_RATIO_MSK)
206		div += MT7620_PLL_DIV_RATIO_BASE;
207	else
208		div = MT7620_PLL_DIV_RATIO_MAX;
209
210	res = (MT7620_XTAL_40 * mul) / div;
211
212	return (MTK_MHZ(res));
213}
214
215static uint32_t
216mtk_detect_cpuclk_mt7621(bus_space_tag_t bst, bus_space_handle_t bsh)
217{
218	uint32_t val, div, res;
219
220	val = bus_space_read_4(bst, bsh, SYSCTL_CLKCFG0);
221	if (val & MT7621_USES_MEMDIV) {
222		div = bus_space_read_4(bst, bsh, MTK_MT7621_CLKDIV_REG);
223		div >>= MT7621_MEMDIV_OFF;
224		div &= MT7621_MEMDIV_MSK;
225		div += MT7621_MEMDIV_BASE;
226
227		val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
228		val >>= MT7621_CLKSEL_OFF;
229		val &= MT7621_CLKSEL_MSK;
230
231		if (val >= MT7621_CLKSEL_25MHZ_VAL)
232			res = div * MT7621_CLKSEL_25MHZ;
233		else if (val >= MT7621_CLKSEL_20MHZ_VAL)
234			res = div * MT7621_CLKSEL_20MHZ;
235		else
236			res = div * 0; /* XXX: not sure about this */
237	} else {
238		val = bus_space_read_4(bst, bsh, SYSCTL_CUR_CLK_STS);
239		div = (val >> MT7621_CLK_STS_DIV_OFF) & MT7621_CLK_STS_MSK;
240		val &= MT7621_CLK_STS_MSK;
241
242		res = (MT7621_CLK_STS_BASE * val) / div;
243	}
244
245	return (MTK_MHZ(res));
246}
247
248static uint32_t
249mtk_detect_cpuclk_mt7628(bus_space_tag_t bst, bus_space_handle_t bsh)
250{
251	uint32_t val;
252
253	val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG);
254	val >>= MT7628_CPU_CLKSEL_OFF;
255	val &= MT7628_CPU_CLKSEL_MSK;
256
257	if (val)
258		return (MTK_CPU_CLK_580MHZ);
259
260	return (MTK_CPU_CLK_575MHZ);
261}
262
263void
264mtk_soc_try_early_detect(void)
265{
266	bus_space_tag_t bst;
267	bus_space_handle_t bsh;
268	uint32_t base;
269	phandle_t node;
270	int i;
271
272	if ((node = OF_finddevice("/")) == -1)
273		return;
274
275	for (i = 0; compat_data[i].ocd_str != NULL; i++) {
276		if (ofw_bus_node_is_compatible(node, compat_data[i].ocd_str)) {
277			mtk_soc_socid = compat_data[i].ocd_data;
278			break;
279		}
280	}
281
282	if (mtk_soc_socid == MTK_SOC_UNKNOWN) {
283		/* We don't know the SoC, so we don't know how to get clocks */
284		return;
285	}
286
287	bst = fdtbus_bs_tag;
288	if (mtk_soc_socid == MTK_SOC_RT2880)
289		base = MTK_RT2880_BASE;
290	else if (mtk_soc_socid == MTK_SOC_MT7621)
291		base = MTK_MT7621_BASE;
292	else
293		base = MTK_DEFAULT_BASE;
294
295	if (bus_space_map(bst, base, MTK_DEFAULT_SIZE, 0, &bsh))
296		return;
297
298	/* First, figure out the CPU clock */
299	switch (mtk_soc_socid) {
300	case MTK_SOC_RT2880:
301		mtk_soc_cpuclk = mtk_detect_cpuclk_rt2880(bst, bsh);
302		break;
303	case MTK_SOC_RT3050:  /* fallthrough */
304	case MTK_SOC_RT3052:
305	case MTK_SOC_RT3350:
306		mtk_soc_cpuclk = mtk_detect_cpuclk_rt305x(bst, bsh);
307		break;
308	case MTK_SOC_RT3352:
309		mtk_soc_cpuclk = mtk_detect_cpuclk_rt3352(bst, bsh);
310		break;
311	case MTK_SOC_RT3662:  /* fallthrough */
312	case MTK_SOC_RT3883:
313		mtk_soc_cpuclk = mtk_detect_cpuclk_rt3883(bst, bsh);
314		break;
315	case MTK_SOC_RT5350:
316		mtk_soc_cpuclk = mtk_detect_cpuclk_rt5350(bst, bsh);
317		break;
318	case MTK_SOC_MT7620A: /* fallthrough */
319	case MTK_SOC_MT7620N:
320		mtk_soc_cpuclk = mtk_detect_cpuclk_mt7620(bst, bsh);
321		break;
322	case MTK_SOC_MT7621:
323		mtk_soc_cpuclk = mtk_detect_cpuclk_mt7621(bst, bsh);
324		break;
325	case MTK_SOC_MT7628:  /* fallthrough */
326	case MTK_SOC_MT7688:
327		mtk_soc_cpuclk = mtk_detect_cpuclk_mt7628(bst, bsh);
328		break;
329	default:
330		/* We don't know the SoC, so we can't find the CPU clock */
331		break;
332	}
333
334	/* Now figure out the timer clock */
335	if (mtk_soc_socid == MTK_SOC_MT7621) {
336#ifdef notyet
337		/*
338		 * We use the GIC timer for timing source and its clock freq is
339		 * the same as the CPU's clock freq
340		 */
341		mtk_soc_timerclk = mtk_soc_cpuclk;
342#else
343		/*
344		 * When GIC timer and MIPS timer are ready to co-exist and
345		 * GIC timer is actually implemented, we need to switch to it.
346		 * Until then we use a fake GIC timer, which is actually a
347		 * normal MIPS ticker, so the timer clock is half the CPU clock
348		 */
349		mtk_soc_timerclk = mtk_soc_cpuclk / 2;
350#endif
351	} else {
352		/*
353		 * We use the MIPS ticker for the rest for now, so
354		 * the CPU clock is divided by 2
355		 */
356		mtk_soc_timerclk = mtk_soc_cpuclk / 2;
357	}
358
359	switch (mtk_soc_socid) {
360	case MTK_SOC_RT2880:
361		mtk_soc_uartclk = mtk_soc_cpuclk / MTK_UARTDIV_2;
362		break;
363	case MTK_SOC_RT3350:  /* fallthrough */
364	case MTK_SOC_RT3050:  /* fallthrough */
365	case MTK_SOC_RT3052:
366		/* UART clock is CPU clock / 3 */
367		mtk_soc_uartclk = mtk_soc_cpuclk / MTK_UARTDIV_3;
368		break;
369	case MTK_SOC_RT3352:  /* fallthrough */
370	case MTK_SOC_RT3662:  /* fallthrough */
371	case MTK_SOC_RT3883:  /* fallthrough */
372	case MTK_SOC_RT5350:  /* fallthrough */
373	case MTK_SOC_MT7620A: /* fallthrough */
374	case MTK_SOC_MT7620N: /* fallthrough */
375	case MTK_SOC_MT7628:  /* fallthrough */
376	case MTK_SOC_MT7688:
377		/* UART clock is always 40MHz */
378		mtk_soc_uartclk = MTK_UART_CLK_40MHZ;
379		break;
380	case MTK_SOC_MT7621:
381		/* UART clock is always 50MHz */
382		mtk_soc_uartclk = MTK_UART_CLK_50MHZ;
383		break;
384	default:
385		/* We don't know the SoC, so we don't know the UART clock */
386		break;
387	}
388
389	bus_space_unmap(bst, bsh, MTK_DEFAULT_SIZE);
390}
391
392uint32_t
393mtk_soc_get_uartclk(void)
394{
395
396	return mtk_soc_uartclk;
397}
398
399uint32_t
400mtk_soc_get_cpuclk(void)
401{
402
403	return mtk_soc_cpuclk;
404}
405
406uint32_t
407mtk_soc_get_timerclk(void)
408{
409
410	return mtk_soc_timerclk;
411}
412
413uint32_t
414mtk_soc_get_socid(void)
415{
416
417	return mtk_soc_socid;
418}
419
420/*
421 * The following are generic reset and clock functions
422 */
423
424/* Default reset time is 100ms */
425#define DEFAULT_RESET_TIME	100000
426
427int
428mtk_soc_reset_device(device_t dev)
429{
430	int res;
431
432	res = fdt_reset_assert_all(dev);
433	if (res == 0) {
434		DELAY(DEFAULT_RESET_TIME);
435		res = fdt_reset_deassert_all(dev);
436		if (res == 0)
437			DELAY(DEFAULT_RESET_TIME);
438	}
439
440	return (res);
441}
442
443int
444mtk_soc_stop_clock(device_t dev)
445{
446
447	return (fdt_clock_disable_all(dev));
448}
449
450int
451mtk_soc_start_clock(device_t dev)
452{
453
454	return (fdt_clock_enable_all(dev));
455}
456
457int
458mtk_soc_assert_reset(device_t dev)
459{
460
461	return (fdt_reset_assert_all(dev));
462}
463
464int
465mtk_soc_deassert_reset(device_t dev)
466{
467
468	return (fdt_reset_deassert_all(dev));
469}
470
471void
472mtk_soc_reset(void)
473{
474
475	mtk_sysctl_clr_set(SYSCTL_RSTCTRL, 0, 1);
476	mtk_sysctl_clr_set(SYSCTL_RSTCTRL, 1, 0);
477}
478