]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/arm/rockchip/rk30xx_mp.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / arm / rockchip / rk30xx_mp.c
1 /*-
2  * Copyright (c) 2014 Ganbold Tsagaankhuu <ganbold@freebsd.org>
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 ``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.
24  */
25
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/bus.h>
31 #include <sys/kernel.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 SCU_PHYSBASE                    0x1013c000
41 #define SCU_SIZE                        0x100
42
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
50
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
55
56 #define IMEM_PHYSBASE                   0x10080000
57 #define IMEM_SIZE                       0x20
58
59 #define PMU_PHYSBASE                    0x20004000
60 #define PMU_SIZE                        0x100
61 #define PMU_PWRDN_CON                   0x08
62 #define PMU_PWRDN_SCU                   (1 << 4)
63
64 extern char     *mpentry_addr;
65 static void      rk30xx_boot2(void);
66
67 static void
68 rk30xx_boot2(void)
69 {
70
71         __asm __volatile(
72                            "ldr pc, 1f\n"
73                            ".globl mpentry_addr\n"
74                            "mpentry_addr:\n"
75                         "1: .space 4\n");
76 }
77
78 void
79 platform_mp_init_secondary(void)
80 {
81
82         gic_init_secondary();
83 }
84
85 void
86 platform_mp_setmaxid(void)
87 {
88         bus_space_handle_t scu;
89         int ncpu;
90         uint32_t val;
91
92         if (mp_ncpus != 0)
93                 return;
94
95         if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE, SCU_SIZE, 0, &scu) != 0)
96                 panic("Could not map the SCU");
97
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);
101
102         mp_ncpus = ncpu;
103         mp_maxid = ncpu - 1;
104 }
105
106 int
107 platform_mp_probe(void)
108 {
109
110         if (mp_ncpus == 0)
111                 platform_mp_setmaxid();
112
113         return (mp_ncpus > 1);
114 }
115
116 void
117 platform_mp_start_ap(void)
118 {
119         bus_space_handle_t scu;
120         bus_space_handle_t imem;
121         bus_space_handle_t pmu;
122         uint32_t val;
123         int i;
124
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");
132
133         /*
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.
137          */
138         bus_space_write_4(fdtbus_bs_tag, scu, SCU_INV_TAGS_REG, 0x0000ffff);
139
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++)
143                 val |= 1 << i;
144         bus_space_write_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON, val);
145
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);
150
151         /* Enable SCU */
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);
155
156         /*
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.
162          *
163          * First set boot function for the sram code.
164          */
165         mpentry_addr = (char *)pmap_kextract((vm_offset_t)mpentry);
166
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);
170
171         cpu_idcache_wbinv_all();
172         cpu_l2cache_wbinv_all();
173
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++)
177                 val &= ~(1 << i);
178         bus_space_write_4(fdtbus_bs_tag, pmu, PMU_PWRDN_CON, val);
179
180         armv7_sev();
181
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);
185 }
186
187 void
188 platform_ipi_send(cpuset_t cpus, u_int ipi)
189 {
190
191         pic_ipi_send(cpus, ipi);
192 }