1/*-
2 * Copyright (c) 2013-2014 Ruslan Bukin <br@bsdpad.com>
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
--- 9 unchanged lines hidden (view full) ---
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: head/sys/arm/samsung/exynos/exynos5_mp.c 267388 2014-06-12 11:37:38Z br $");
29#include <sys/param.h>
30#include <sys/systm.h>
31#include <sys/bus.h>
32#include <sys/lock.h>
33#include <sys/mutex.h>
34#include <sys/smp.h>
35
36#include <machine/smp.h>
37#include <machine/fdt.h>
38#include <machine/intr.h>
39
40#define EXYNOS_CHIPID 0x10000000
41
42#define EXYNOS5250_SOC_ID 0x43520000
43#define EXYNOS5420_SOC_ID 0xE5420000
44#define EXYNOS5_SOC_ID_MASK 0xFFFFF000
45
46#define EXYNOS_SYSRAM 0x02020000
47#define EXYNOS5420_SYSRAM_NS (EXYNOS_SYSRAM + 0x53000 + 0x1c)
48
49#define EXYNOS_PMU_BASE 0x10040000
50#define CORE_CONFIG(n) (0x2000 + (0x80 * (n)))
51#define CORE_STATUS(n) (CORE_CONFIG(n) + 0x4)
52#define CORE_PWR_EN 0x3
53
54static int
55exynos_get_soc_id(void)
56{
57 bus_addr_t chipid;
58 int reg;
59
60 if (bus_space_map(fdtbus_bs_tag, EXYNOS_CHIPID,
61 0x1000, 0, &chipid) != 0)
62 panic("Couldn't map chipid\n");
63 reg = bus_space_read_4(fdtbus_bs_tag, chipid, 0x0);
64 bus_space_unmap(fdtbus_bs_tag, chipid, 0x1000);
65
66 return (reg & EXYNOS5_SOC_ID_MASK);
67}
68
69void
70platform_mp_init_secondary(void)
71{
72
73 gic_init_secondary();
74}
75
76void
77platform_mp_setmaxid(void)
78{
79
80 if (exynos_get_soc_id() == EXYNOS5420_SOC_ID)
81 mp_ncpus = 4;
82 else
83 mp_ncpus = 2;
84
85 mp_maxid = mp_ncpus - 1;
86}
87
88int
89platform_mp_probe(void)
90{
91
92 return (mp_ncpus > 1);
93}
94
95void
96platform_mp_start_ap(void)
97{
98 bus_addr_t sysram, pmu;
99 int err, i, j;
100 int status;
101 int reg;
102
103 err = bus_space_map(fdtbus_bs_tag, EXYNOS_PMU_BASE, 0x20000, 0, &pmu);
104 if (err != 0)
105 panic("Couldn't map pmu\n");
106
107 if (exynos_get_soc_id() == EXYNOS5420_SOC_ID)
108 reg = EXYNOS5420_SYSRAM_NS;
109 else
110 reg = EXYNOS_SYSRAM;
111
112 err = bus_space_map(fdtbus_bs_tag, reg, 0x100, 0, &sysram);
113 if (err != 0)
114 panic("Couldn't map sysram\n");
115
116 /* Give power to CPUs */
117 for (i = 1; i < mp_ncpus; i++) {
118 bus_space_write_4(fdtbus_bs_tag, pmu, CORE_CONFIG(i),
119 CORE_PWR_EN);
120
121 for (j = 10; j >= 0; j--) {
122 status = bus_space_read_4(fdtbus_bs_tag, pmu,
123 CORE_STATUS(i));
124 if ((status & CORE_PWR_EN) == CORE_PWR_EN)
125 break;
126 DELAY(10);
127 if (j == 0)
128 printf("Can't power on CPU%d\n", i);
129 }
130 }
131
132 bus_space_write_4(fdtbus_bs_tag, sysram, 0x0,
133 pmap_kextract((vm_offset_t)mpentry));
134
135 cpu_idcache_wbinv_all();
136 cpu_l2cache_wbinv_all();
137
138 armv7_sev();
139 bus_space_unmap(fdtbus_bs_tag, sysram, 0x100);
140 bus_space_unmap(fdtbus_bs_tag, pmu, 0x20000);
141}
142
143void
144platform_ipi_send(cpuset_t cpus, u_int ipi)
145{
146
147 pic_ipi_send(cpus, ipi);
148}
2 * Copyright (c) 2013-2014 Ruslan Bukin <br@bsdpad.com>
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
--- 9 unchanged lines hidden (view full) ---
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: head/sys/arm/samsung/exynos/exynos5_mp.c 267388 2014-06-12 11:37:38Z br $");
29#include <sys/param.h>
30#include <sys/systm.h>
31#include <sys/bus.h>
32#include <sys/lock.h>
33#include <sys/mutex.h>
34#include <sys/smp.h>
35
36#include <machine/smp.h>
37#include <machine/fdt.h>
38#include <machine/intr.h>
39
40#define EXYNOS_CHIPID 0x10000000
41
42#define EXYNOS5250_SOC_ID 0x43520000
43#define EXYNOS5420_SOC_ID 0xE5420000
44#define EXYNOS5_SOC_ID_MASK 0xFFFFF000
45
46#define EXYNOS_SYSRAM 0x02020000
47#define EXYNOS5420_SYSRAM_NS (EXYNOS_SYSRAM + 0x53000 + 0x1c)
48
49#define EXYNOS_PMU_BASE 0x10040000
50#define CORE_CONFIG(n) (0x2000 + (0x80 * (n)))
51#define CORE_STATUS(n) (CORE_CONFIG(n) + 0x4)
52#define CORE_PWR_EN 0x3
53
54static int
55exynos_get_soc_id(void)
56{
57 bus_addr_t chipid;
58 int reg;
59
60 if (bus_space_map(fdtbus_bs_tag, EXYNOS_CHIPID,
61 0x1000, 0, &chipid) != 0)
62 panic("Couldn't map chipid\n");
63 reg = bus_space_read_4(fdtbus_bs_tag, chipid, 0x0);
64 bus_space_unmap(fdtbus_bs_tag, chipid, 0x1000);
65
66 return (reg & EXYNOS5_SOC_ID_MASK);
67}
68
69void
70platform_mp_init_secondary(void)
71{
72
73 gic_init_secondary();
74}
75
76void
77platform_mp_setmaxid(void)
78{
79
80 if (exynos_get_soc_id() == EXYNOS5420_SOC_ID)
81 mp_ncpus = 4;
82 else
83 mp_ncpus = 2;
84
85 mp_maxid = mp_ncpus - 1;
86}
87
88int
89platform_mp_probe(void)
90{
91
92 return (mp_ncpus > 1);
93}
94
95void
96platform_mp_start_ap(void)
97{
98 bus_addr_t sysram, pmu;
99 int err, i, j;
100 int status;
101 int reg;
102
103 err = bus_space_map(fdtbus_bs_tag, EXYNOS_PMU_BASE, 0x20000, 0, &pmu);
104 if (err != 0)
105 panic("Couldn't map pmu\n");
106
107 if (exynos_get_soc_id() == EXYNOS5420_SOC_ID)
108 reg = EXYNOS5420_SYSRAM_NS;
109 else
110 reg = EXYNOS_SYSRAM;
111
112 err = bus_space_map(fdtbus_bs_tag, reg, 0x100, 0, &sysram);
113 if (err != 0)
114 panic("Couldn't map sysram\n");
115
116 /* Give power to CPUs */
117 for (i = 1; i < mp_ncpus; i++) {
118 bus_space_write_4(fdtbus_bs_tag, pmu, CORE_CONFIG(i),
119 CORE_PWR_EN);
120
121 for (j = 10; j >= 0; j--) {
122 status = bus_space_read_4(fdtbus_bs_tag, pmu,
123 CORE_STATUS(i));
124 if ((status & CORE_PWR_EN) == CORE_PWR_EN)
125 break;
126 DELAY(10);
127 if (j == 0)
128 printf("Can't power on CPU%d\n", i);
129 }
130 }
131
132 bus_space_write_4(fdtbus_bs_tag, sysram, 0x0,
133 pmap_kextract((vm_offset_t)mpentry));
134
135 cpu_idcache_wbinv_all();
136 cpu_l2cache_wbinv_all();
137
138 armv7_sev();
139 bus_space_unmap(fdtbus_bs_tag, sysram, 0x100);
140 bus_space_unmap(fdtbus_bs_tag, pmu, 0x20000);
141}
142
143void
144platform_ipi_send(cpuset_t cpus, u_int ipi)
145{
146
147 pic_ipi_send(cpus, ipi);
148}