Skip to content

Commit b4004e8

Browse files
committed
cpu: enabling and disabling slave cores
Implements full flow for enabling and disabling slave cores. Core power operations availability based on architecture. Signed-off-by: Tomasz Lauda <tomasz.lauda@linux.intel.com>
1 parent 50ee7c5 commit b4004e8

16 files changed

Lines changed: 342 additions & 17 deletions

File tree

src/arch/xtensa/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,15 @@ if BUILD_XTENSA_SMP
5252
sof_SOURCES += \
5353
smp/xtos/crt1-boards.S \
5454
smp/xtos/_vectors.S \
55+
smp/cpu.c \
5556
smp/init.c \
5657
smp/schedule.c \
5758
smp/task.c
5859
else
5960
sof_SOURCES += \
6061
up/xtos/crt1-boards.S \
6162
up/xtos/_vectors.S \
63+
up/cpu.c \
6264
up/init.c \
6365
up/schedule.c \
6466
up/task.c

src/arch/xtensa/include/arch/cpu.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@
3535
#include <xtensa/config/core.h>
3636
#include <platform/platcfg.h>
3737

38-
static inline int cpu_get_id(void)
38+
void arch_cpu_enable_core(int id);
39+
40+
void arch_cpu_disable_core(int id);
41+
42+
static inline int arch_cpu_get_id(void)
3943
{
4044
int prid;
4145
#if XCHAL_HAVE_PRID

src/arch/xtensa/smp/cpu.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Copyright (c) 2018, Intel Corporation
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 are met:
7+
* * Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* * Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
* * Neither the name of the Intel Corporation nor the
13+
* names of its contributors may be used to endorse or promote products
14+
* derived from this software without specific prior written permission.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
*
28+
* Author: Tomasz Lauda <tomasz.lauda@linux.intel.com>
29+
*
30+
*/
31+
32+
/**
33+
* \file arch/xtensa/smp/cpu.c
34+
* \brief Xtensa SMP CPU implementation file
35+
* \authors Tomasz Lauda <tomasz.lauda@linux.intel.com>
36+
*/
37+
38+
#include <arch/alloc.h>
39+
#include <arch/atomic.h>
40+
#include <arch/cpu.h>
41+
#include <arch/idc.h>
42+
#include <platform/platform.h>
43+
#include <sof/lock.h>
44+
#include <sof/schedule.h>
45+
46+
static uint32_t active_cores_mask = 0x1;
47+
static spinlock_t lock = { 0 };
48+
49+
void arch_cpu_enable_core(int id)
50+
{
51+
struct idc_msg power_up = {
52+
IDC_POWER_UP_MESSAGE, IDC_POWER_UP_EXTENSION, id };
53+
uint32_t flags;
54+
55+
spin_lock_irq(&lock, flags);
56+
57+
if (!(active_cores_mask & (1 << id))) {
58+
/* allocate resources for core */
59+
alloc_core_context(id);
60+
61+
/* enable IDC interrupt for the the slave core */
62+
idc_enable_interrupts(id, arch_cpu_get_id());
63+
64+
/* send IDC power up message */
65+
arch_idc_send_msg(&power_up);
66+
67+
active_cores_mask |= (1 << id);
68+
}
69+
70+
spin_unlock_irq(&lock, flags);
71+
}
72+
73+
void arch_cpu_disable_core(int id)
74+
{
75+
struct idc_msg power_down = { IDC_POWER_DOWN_MESSAGE, 0, id };
76+
uint32_t flags;
77+
78+
spin_lock_irq(&lock, flags);
79+
80+
if (active_cores_mask & (1 << id)) {
81+
arch_idc_send_msg(&power_down);
82+
83+
active_cores_mask ^= (1 << id);
84+
}
85+
86+
spin_unlock_irq(&lock, flags);
87+
}
88+
89+
void cpu_power_down_core(void)
90+
{
91+
arch_interrupt_global_disable();
92+
93+
idc_free();
94+
95+
scheduler_free();
96+
97+
free_core_context(arch_cpu_get_id());
98+
99+
dcache_writeback_invalidate_all();
100+
101+
while (1)
102+
arch_wait_for_interrupt(0);
103+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
noinst_HEADERS = \
2+
alloc.h \
23
idc.h
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright (c) 2018, Intel Corporation
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 are met:
7+
* * Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* * Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
* * Neither the name of the Intel Corporation nor the
13+
* names of its contributors may be used to endorse or promote products
14+
* derived from this software without specific prior written permission.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
*
28+
* Author: Tomasz Lauda <tomasz.lauda@linux.intel.com>
29+
*/
30+
31+
/**
32+
* \file arch/xtensa/smp/include/arch/alloc.h
33+
* \brief Xtensa SMP memory allocation header file
34+
* \authors Tomasz Lauda <tomasz.lauda@linux.intel.com>
35+
*/
36+
37+
#ifndef __ARCH_ALLOC_H__
38+
#define __ARCH_ALLOC_H__
39+
40+
#include <xtos-structs.h>
41+
#include <sof/alloc.h>
42+
43+
extern struct core_context *core_ctx_ptr[PLATFORM_CORE_COUNT];
44+
extern struct xtos_core_data *core_data_ptr[PLATFORM_CORE_COUNT];
45+
46+
/**
47+
* \brief Allocates memory for core specific data.
48+
* \param[in] core Slave core for which data needs to be allocated.
49+
*/
50+
static inline void alloc_core_context(int core)
51+
{
52+
struct core_context *core_ctx;
53+
54+
core_ctx = rzalloc(RZONE_RUNTIME, SOF_MEM_CAPS_RAM, sizeof(*core_ctx));
55+
dcache_writeback_invalidate_region(core_ctx, sizeof(*core_ctx));
56+
57+
/* xtos_core_data is a big struct, so allocate it from system heap
58+
* and never free again. Allocating from runtime heap would be
59+
* a waste of a very big memory block.
60+
*/
61+
if (!core_data_ptr[core])
62+
core_data_ptr[core] = rzalloc(RZONE_SYS, SOF_MEM_CAPS_RAM,
63+
sizeof(*core_data_ptr[core]));
64+
65+
core_data_ptr[core]->thread_data_ptr = &core_ctx->td;
66+
dcache_writeback_invalidate_region(core_data_ptr[core],
67+
sizeof(*core_data_ptr[core]));
68+
69+
dcache_writeback_invalidate_region(core_data_ptr,
70+
sizeof(core_data_ptr));
71+
72+
core_ctx_ptr[core] = core_ctx;
73+
dcache_writeback_invalidate_region(core_ctx_ptr,
74+
sizeof(core_ctx_ptr));
75+
}
76+
77+
/**
78+
* \brief Frees memory allocated for core specific data.
79+
* \param[in] core Slave core for which data needs to be freed.
80+
*/
81+
static inline void free_core_context(int core)
82+
{
83+
rfree(core_ctx_ptr[core]);
84+
dcache_writeback_invalidate_region(core_ctx_ptr[core],
85+
sizeof(*core_ctx_ptr[core]));
86+
}
87+
88+
#endif

src/arch/xtensa/smp/include/arch/idc.h

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,25 @@
5454
/** \brief IDC trace error function. */
5555
#define trace_idc_error(__e) trace_error(TRACE_CLASS_IDC, __e)
5656

57-
/** \brief IDC header mask. */
58-
#define IDC_HEADER(x) ((x) & 0x7fffffff)
5957

60-
/** \brief IDC extension mask. */
61-
#define IDC_EXTENSION(x) ((x) & 0x0fffffff)
58+
/** \brief ROM wake version parsed by ROM during core wake up. */
59+
#define IDC_ROM_WAKE_VERSION 0x2
60+
61+
/** \brief ROM control version parsed by ROM during core wake up. */
62+
#define IDC_ROM_CONTROL_VERSION 0x1
63+
64+
// TODO: refactor below defines after universal IDC message template
65+
// will be defined and ready
66+
67+
/** \brief Power up message header. */
68+
#define IDC_POWER_UP_MESSAGE \
69+
(IDC_ROM_WAKE_VERSION | (IDC_ROM_CONTROL_VERSION << 24))
70+
71+
/** \brief Power up message extension. */
72+
#define IDC_POWER_UP_EXTENSION (SOF_TEXT_START >> 2)
73+
74+
/** \brief Power down message header. */
75+
#define IDC_POWER_DOWN_MESSAGE 0x7FFFFFFF
6276

6377
/** \brief IDC message. */
6478
struct idc_msg {
@@ -76,6 +90,8 @@ struct idc {
7690
struct idc_msg received_msg; /**< received message */
7791
};
7892

93+
extern void cpu_power_down_core(void);
94+
7995
/**
8096
* \brief Returns IDC data.
8197
* \return Pointer to pointer of IDC data.
@@ -87,14 +103,21 @@ static inline struct idc **idc_get(void)
87103
return &ctx->idc;
88104
}
89105

106+
static inline void idc_enable_interrupts(int target_core, int source_core)
107+
{
108+
idc_write(IPC_IDCCTL, target_core,
109+
IPC_IDCCTL_IDCTBIE(source_core));
110+
platform_interrupt_unmask(PLATFORM_IDC_INTERRUPT(target_core), 0);
111+
}
112+
90113
/**
91114
* \brief IDC interrupt handler.
92115
* \param[in,out] arg Pointer to IDC data.
93116
*/
94117
static void idc_irq_handler(void *arg)
95118
{
96119
struct idc *idc = arg;
97-
int core = cpu_get_id();
120+
int core = arch_cpu_get_id();
98121
uint32_t idctfc;
99122
uint32_t idctefc;
100123
uint32_t idcietc;
@@ -146,7 +169,7 @@ static void idc_irq_handler(void *arg)
146169
static inline void arch_idc_send_msg(struct idc_msg *msg)
147170
{
148171
struct idc *idc = *idc_get();
149-
int core = cpu_get_id();
172+
int core = arch_cpu_get_id();
150173
uint32_t flags;
151174

152175
tracev_idc("Msg");
@@ -166,7 +189,11 @@ static inline void arch_idc_send_msg(struct idc_msg *msg)
166189
*/
167190
static inline int32_t idc_cmd(struct idc_msg *msg)
168191
{
169-
/* execute message based on type */
192+
/* right now we only handle power down */
193+
/* TODO: universal implementation */
194+
if (msg->header == IDC_POWER_DOWN_MESSAGE)
195+
cpu_power_down_core();
196+
170197
return 0;
171198
}
172199

@@ -176,7 +203,7 @@ static inline int32_t idc_cmd(struct idc_msg *msg)
176203
*/
177204
static inline void idc_do_cmd(struct idc *idc)
178205
{
179-
int core = cpu_get_id();
206+
int core = arch_cpu_get_id();
180207
int initiator = idc->received_msg.core;
181208

182209
trace_idc("Cmd");
@@ -253,7 +280,7 @@ static inline uint32_t idc_get_done_bit_mask(int core)
253280
*/
254281
static inline void arch_idc_init(void)
255282
{
256-
int core = cpu_get_id();
283+
int core = arch_cpu_get_id();
257284

258285
trace_idc("IDI");
259286

src/arch/xtensa/smp/init.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ struct xtos_core_data *core_data_ptr[PLATFORM_CORE_COUNT];
7171
*/
7272
static void initialize_pointers_per_core(void)
7373
{
74-
int core = cpu_get_id();
74+
int core = arch_cpu_get_id();
7575
struct xtos_core_data *core_data = core_data_ptr[core];
7676

7777
if (core == PLATFORM_MASTER_CORE_ID) {

src/arch/xtensa/smp/xtos/int-sethandler.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ _xtos_handler _xtos_set_interrupt_handler_arg( int n, _xtos_handler f, void *arg
4242
ret = 0; /* priority level too high to safely handle in C */
4343
}
4444
else {
45-
entry = &(core_data_ptr[cpu_get_id()]->xtos_int_data.xtos_interrupt_table.array[MAPINT(n)]);
45+
entry = &(core_data_ptr[arch_cpu_get_id()]->xtos_int_data.xtos_interrupt_table.array[MAPINT(n)]);
4646
old = entry->handler;
4747
if (f) {
4848
entry->handler = f;

src/arch/xtensa/up/cpu.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) 2018, Intel Corporation
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 are met:
7+
* * Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* * Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
* * Neither the name of the Intel Corporation nor the
13+
* names of its contributors may be used to endorse or promote products
14+
* derived from this software without specific prior written permission.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
*
28+
* Author: Tomasz Lauda <tomasz.lauda@linux.intel.com>
29+
*
30+
*/
31+
32+
/**
33+
* \file arch/xtensa/up/cpu.c
34+
* \brief Xtensa UP CPU implementation file
35+
* \authors Tomasz Lauda <tomasz.lauda@linux.intel.com>
36+
*/
37+
38+
#include <arch/cpu.h>
39+
40+
void arch_cpu_enable_core(int id) { }
41+
42+
void arch_cpu_disable_core(int id) { }

src/include/sof/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ include_HEADERS = \
99
alloc.h \
1010
atomic.h \
1111
clock.h \
12+
cpu.h \
1213
dai.h \
1314
debug.h \
1415
dma.h \

0 commit comments

Comments
 (0)