1252391Sray/*-
2267388Sbr * Copyright (c) 2013-2014 Ruslan Bukin <br@bsdpad.com>
3252391Sray * All rights reserved.
4252391Sray *
5252391Sray * Redistribution and use in source and binary forms, with or without
6252391Sray * modification, are permitted provided that the following conditions
7252391Sray * are met:
8252391Sray * 1. Redistributions of source code must retain the above copyright
9252391Sray *    notice, this list of conditions and the following disclaimer.
10252391Sray * 2. Redistributions in binary form must reproduce the above copyright
11252391Sray *    notice, this list of conditions and the following disclaimer in the
12252391Sray *    documentation and/or other materials provided with the distribution.
13252391Sray *
14252391Sray * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15252391Sray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16252391Sray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17252391Sray * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18252391Sray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19252391Sray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20252391Sray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21252391Sray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22252391Sray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23252391Sray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24252391Sray * SUCH DAMAGE.
25252391Sray */
26252391Sray
27252391Sray#include <sys/cdefs.h>
28252391Sray__FBSDID("$FreeBSD: stable/11/sys/arm/samsung/exynos/exynos5_mp.c 307344 2016-10-15 08:27:54Z mmel $");
29252391Sray#include <sys/param.h>
30252391Sray#include <sys/systm.h>
31252391Sray#include <sys/bus.h>
32252391Sray#include <sys/lock.h>
33252391Sray#include <sys/mutex.h>
34252391Sray#include <sys/smp.h>
35252391Sray
36281092Sandrew#include <vm/vm.h>
37281092Sandrew#include <vm/pmap.h>
38281092Sandrew
39295319Smmel#include <machine/cpu.h>
40252391Sray#include <machine/smp.h>
41252391Sray#include <machine/fdt.h>
42252391Sray#include <machine/intr.h>
43252391Sray
44267388Sbr#define	EXYNOS_CHIPID		0x10000000
45252391Sray
46267388Sbr#define	EXYNOS5250_SOC_ID	0x43520000
47267388Sbr#define	EXYNOS5420_SOC_ID	0xE5420000
48267388Sbr#define	EXYNOS5_SOC_ID_MASK	0xFFFFF000
49267388Sbr
50267388Sbr#define	EXYNOS_SYSRAM		0x02020000
51267388Sbr#define	EXYNOS5420_SYSRAM_NS	(EXYNOS_SYSRAM + 0x53000 + 0x1c)
52267388Sbr
53267388Sbr#define	EXYNOS_PMU_BASE		0x10040000
54267388Sbr#define	CORE_CONFIG(n)		(0x2000 + (0x80 * (n)))
55267388Sbr#define	CORE_STATUS(n)		(CORE_CONFIG(n) + 0x4)
56267388Sbr#define	CORE_PWR_EN		0x3
57267388Sbr
58267388Sbrstatic int
59267388Sbrexynos_get_soc_id(void)
60267388Sbr{
61267388Sbr	bus_addr_t chipid;
62267388Sbr	int reg;
63267388Sbr
64267388Sbr	if (bus_space_map(fdtbus_bs_tag, EXYNOS_CHIPID,
65267388Sbr		0x1000, 0, &chipid) != 0)
66267388Sbr		panic("Couldn't map chipid\n");
67267388Sbr	reg = bus_space_read_4(fdtbus_bs_tag, chipid, 0x0);
68267388Sbr	bus_space_unmap(fdtbus_bs_tag, chipid, 0x1000);
69267388Sbr
70267388Sbr	return (reg & EXYNOS5_SOC_ID_MASK);
71267388Sbr}
72267388Sbr
73252391Srayvoid
74252391Srayplatform_mp_setmaxid(void)
75252391Sray{
76252391Sray
77267388Sbr	if (exynos_get_soc_id() == EXYNOS5420_SOC_ID)
78267388Sbr		mp_ncpus = 4;
79267388Sbr	else
80267388Sbr		mp_ncpus = 2;
81267388Sbr
82267388Sbr	mp_maxid = mp_ncpus - 1;
83252391Sray}
84252391Sray
85252391Srayvoid
86252391Srayplatform_mp_start_ap(void)
87252391Sray{
88267388Sbr	bus_addr_t sysram, pmu;
89267388Sbr	int err, i, j;
90267388Sbr	int status;
91267388Sbr	int reg;
92252391Sray
93267388Sbr	err = bus_space_map(fdtbus_bs_tag, EXYNOS_PMU_BASE, 0x20000, 0, &pmu);
94252391Sray	if (err != 0)
95267388Sbr		panic("Couldn't map pmu\n");
96267388Sbr
97267388Sbr	if (exynos_get_soc_id() == EXYNOS5420_SOC_ID)
98267388Sbr		reg = EXYNOS5420_SYSRAM_NS;
99267388Sbr	else
100267388Sbr		reg = EXYNOS_SYSRAM;
101267388Sbr
102267388Sbr	err = bus_space_map(fdtbus_bs_tag, reg, 0x100, 0, &sysram);
103267388Sbr	if (err != 0)
104252391Sray		panic("Couldn't map sysram\n");
105252391Sray
106267388Sbr	/* Give power to CPUs */
107267388Sbr	for (i = 1; i < mp_ncpus; i++) {
108267388Sbr		bus_space_write_4(fdtbus_bs_tag, pmu, CORE_CONFIG(i),
109267388Sbr		    CORE_PWR_EN);
110267388Sbr
111267388Sbr		for (j = 10; j >= 0; j--) {
112267388Sbr			status = bus_space_read_4(fdtbus_bs_tag, pmu,
113267388Sbr			    CORE_STATUS(i));
114267388Sbr			if ((status & CORE_PWR_EN) == CORE_PWR_EN)
115267388Sbr				break;
116267388Sbr			DELAY(10);
117267388Sbr			if (j == 0)
118267388Sbr				printf("Can't power on CPU%d\n", i);
119267388Sbr		}
120267388Sbr	}
121267388Sbr
122252391Sray	bus_space_write_4(fdtbus_bs_tag, sysram, 0x0,
123252391Sray	    pmap_kextract((vm_offset_t)mpentry));
124252391Sray
125295319Smmel	dcache_wbinv_poc_all();
126252391Sray
127307344Smmel	dsb();
128307344Smmel	sev();
129252391Sray	bus_space_unmap(fdtbus_bs_tag, sysram, 0x100);
130267388Sbr	bus_space_unmap(fdtbus_bs_tag, pmu, 0x20000);
131252391Sray}
132