2 * Copyright (c) 2014 Ganbold Tsagaankhuu <ganbold@freebsd.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28 #include <sys/param.h>
29 #include <sys/systm.h>
31 #include <sys/kernel.h>
33 #include <sys/mutex.h>
36 #include <machine/smp.h>
37 #include <machine/fdt.h>
38 #include <machine/intr.h>
40 #define SCU_PHYSBASE 0x1013c000
41 #define SCU_SIZE 0x100
43 #define SCU_CONTROL_REG 0x00
44 #define SCU_CONTROL_ENABLE (1 << 0)
45 #define SCU_STANDBY_EN (1 << 5)
46 #define SCU_CONFIG_REG 0x04
47 #define SCU_CONFIG_REG_NCPU_MASK 0x03
48 #define SCU_CPUPOWER_REG 0x08
49 #define SCU_INV_TAGS_REG 0x0c
51 #define SCU_FILTER_START_REG 0x10
52 #define SCU_FILTER_END_REG 0x14
53 #define SCU_SECURE_ACCESS_REG 0x18
54 #define SCU_NONSECURE_ACCESS_REG 0x1c
56 #define IMEM_PHYSBASE 0x10080000
57 #define IMEM_SIZE 0x20
59 #define PMU_PHYSBASE 0x20004000
60 #define PMU_SIZE 0x100
61 #define PMU_PWRDN_CON 0x08
62 #define PMU_PWRDN_SCU (1 << 4)
64 extern char *mpentry_addr;
65 static void rk30xx_boot2(void);
73 ".globl mpentry_addr\n"
79 platform_mp_init_secondary(void)
86 platform_mp_setmaxid(void)
88 bus_space_handle_t scu;
95 if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0)
96 panic("Could not map the SCU");
98 val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONFIG_REG);
99 ncpu = (val & SCU_CONFIG_REG_NCPU_MASK) + 1;
100 bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE);
107 platform_mp_probe(void)
111 platform_mp_setmaxid();
113 return (mp_ncpus > 1);
117 platform_mp_start_ap(void)
119 bus_space_handle_t scu;
120 bus_space_handle_t imem;
121 bus_space_handle_t pmu;
125 if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0)
126 panic("Could not map the SCU");
127 if (bus_space_map(fdtbus_bs_tag, IMEM_PHYSBASE,
128 IMEM_SIZE, 0, &imem) != 0)
129 panic("Could not map the IMEM");
130 if (bus_space_map(fdtbus_bs_tag, PMU_PHYSBASE, PMU_SIZE, 0, &pmu) != 0)
131 panic("Could not map the PMU");
134 * Invalidate SCU cache tags. The 0x0000ffff constant invalidates all
135 * ways on all cores 0-3. Per the ARM docs, it's harmless to write to
136 * the bits for cores that are not present.
138 bus_space_write_4(fdtbus_bs_tag, scu, SCU_INV_TAGS_REG, 0x0000ffff);
140 /* Make sure all cores except the first are off */
141 val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON);
142 for (i = 1; i < mp_ncpus; i++)
144 bus_space_write_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON, val);
146 /* Enable SCU power domain */
147 val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON);
148 val &= ~PMU_PWRDN_SCU;
149 bus_space_write_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON, val);
152 val = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG);
153 bus_space_write_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG,
154 val | SCU_CONTROL_ENABLE);
157 * Cores will execute the code which resides at the start of
158 * the on-chip bootram/sram after power-on. This sram region
159 * should be reserved and the trampoline code that directs
160 * the core to the real startup code in ram should be copied
161 * into this sram region.
163 * First set boot function for the sram code.
165 mpentry_addr = (char *)pmap_kextract((vm_offset_t)mpentry);
167 /* Copy trampoline to sram, that runs during startup of the core */
168 bus_space_write_region_4(fdtbus_bs_tag, imem, 0,
169 (uint32_t *)&rk30xx_boot2, 8);
171 cpu_idcache_wbinv_all();
172 cpu_l2cache_wbinv_all();
174 /* Start all cores */
175 val = bus_space_read_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON);
176 for (i = 1; i < mp_ncpus; i++)
178 bus_space_write_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON, val);
182 bus_space_unmap(fdtbus_bs_tag, scu, SCU_SIZE);
183 bus_space_unmap(fdtbus_bs_tag, imem, IMEM_SIZE);
184 bus_space_unmap(fdtbus_bs_tag, pmu, PMU_SIZE);
188 platform_ipi_send(cpuset_t cpus, u_int ipi)
191 pic_ipi_send(cpus, ipi);