Skip to content

Commit 0cda98d

Browse files
authored
Merge pull request #42 from tlauda/topic/idc
idc: intra DSP communication
2 parents a845daf + b31c743 commit 0cda98d

30 files changed

Lines changed: 638 additions & 10 deletions

File tree

Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@ ARCH_INCDIR = -I $(SRC_DIR)/arch/$(ARCH)/include
3131

3232
if BUILD_XTENSA_SMP
3333
ARCH_INCDIR += \
34+
-I $(SRC_DIR)/arch/$(ARCH)/smp/include \
3435
-I $(SRC_DIR)/arch/$(ARCH)/smp/xtos
3536
else
3637
ARCH_INCDIR += \
38+
-I $(SRC_DIR)/arch/$(ARCH)/up/include \
3739
-I $(SRC_DIR)/arch/$(ARCH)/up/xtos
3840
endif
3941

configure.ac

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,9 +427,13 @@ AC_CONFIG_FILES([
427427
src/arch/xtensa/include/xtensa/config/Makefile
428428
src/arch/xtensa/smp/Makefile
429429
src/arch/xtensa/smp/hal/Makefile
430+
src/arch/xtensa/smp/include/Makefile
431+
src/arch/xtensa/smp/include/arch/Makefile
430432
src/arch/xtensa/smp/xtos/Makefile
431433
src/arch/xtensa/up/Makefile
432434
src/arch/xtensa/up/hal/Makefile
435+
src/arch/xtensa/up/include/Makefile
436+
src/arch/xtensa/up/include/arch/Makefile
433437
src/arch/xtensa/up/xtos/Makefile
434438
src/arch/host/Makefile
435439
src/arch/host/include/Makefile

src/arch/xtensa/smp/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
SUBDIRS = hal xtos
1+
SUBDIRS = hal include xtos
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
SUBDIRS = arch
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
noinst_HEADERS = \
2+
idc.h
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
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/idc.h
33+
* \brief Xtensa SMP architecture IDC header file
34+
* \authors Tomasz Lauda <tomasz.lauda@linux.intel.com>
35+
*/
36+
37+
#ifndef __ARCH_IDC_H__
38+
#define __ARCH_IDC_H__
39+
40+
#include <xtos-structs.h>
41+
#include <arch/cpu.h>
42+
#include <platform/interrupt.h>
43+
#include <platform/platform.h>
44+
#include <sof/alloc.h>
45+
#include <sof/lock.h>
46+
#include <sof/trace.h>
47+
48+
/** \brief IDC trace function. */
49+
#define trace_idc(__e) trace_event(TRACE_CLASS_IDC, __e)
50+
51+
/** \brief IDC trace value function. */
52+
#define tracev_idc(__e) tracev_event(TRACE_CLASS_IDC, __e)
53+
54+
/** \brief IDC trace error function. */
55+
#define trace_idc_error(__e) trace_error(TRACE_CLASS_IDC, __e)
56+
57+
/** \brief IDC header mask. */
58+
#define IDC_HEADER(x) ((x) & 0x7fffffff)
59+
60+
/** \brief IDC extension mask. */
61+
#define IDC_EXTENSION(x) ((x) & 0x0fffffff)
62+
63+
/** \brief IDC message. */
64+
struct idc_msg {
65+
uint32_t header; /**< header value */
66+
uint32_t extension; /**< extension value */
67+
uint32_t core; /**< core id */
68+
};
69+
70+
/** \brief IDC data. */
71+
struct idc {
72+
spinlock_t lock; /**< lock mechanism */
73+
uint32_t busy_bit_mask; /**< busy interrupt mask */
74+
uint32_t done_bit_mask; /**< done interrupt mask */
75+
uint32_t msg_pending; /**< is message pending */
76+
struct idc_msg received_msg; /**< received message */
77+
struct idc_msg msg_to_send; /**< message to be sent */
78+
};
79+
80+
/**
81+
* \brief Returns IDC data.
82+
* \return Pointer to pointer of IDC data.
83+
*/
84+
static inline struct idc **idc_get(void)
85+
{
86+
struct core_context *ctx = (struct core_context *)cpu_read_threadptr();
87+
88+
return &ctx->idc;
89+
}
90+
91+
/**
92+
* \brief IDC interrupt handler.
93+
* \param[in,out] arg Pointer to IDC data.
94+
*/
95+
static void idc_irq_handler(void *arg)
96+
{
97+
struct idc *idc = arg;
98+
int core = cpu_get_id();
99+
uint32_t idctfc;
100+
uint32_t idctefc;
101+
uint32_t idcietc;
102+
uint32_t i;
103+
104+
tracev_idc("IRQ");
105+
106+
for (i = 0; i < PLATFORM_CORE_COUNT; i++) {
107+
idctfc = idc_read(IPC_IDCTFC(i), core);
108+
109+
if (idctfc & IPC_IDCTFC_BUSY) {
110+
trace_idc("Nms");
111+
112+
/* disable BUSY interrupt */
113+
idc_write(IPC_IDCCTL, core, idc->done_bit_mask);
114+
115+
idc->received_msg.core = i;
116+
idc->received_msg.header =
117+
idctfc & IPC_IDCTFC_MSG_MASK;
118+
119+
idctefc = idc_read(IPC_IDCTEFC(i), core);
120+
idc->received_msg.extension =
121+
idctefc & IPC_IDCTEFC_MSG_MASK;
122+
123+
idc->msg_pending = 1;
124+
125+
break;
126+
}
127+
}
128+
129+
for (i = 0; i < PLATFORM_CORE_COUNT; i++) {
130+
idcietc = idc_read(IPC_IDCIETC(i), core);
131+
132+
if (idcietc & IPC_IDCIETC_DONE) {
133+
tracev_idc("Rpy");
134+
135+
idc_write(IPC_IDCIETC(i), core,
136+
idcietc | IPC_IDCIETC_DONE);
137+
138+
break;
139+
}
140+
}
141+
}
142+
143+
/**
144+
* \brief Sends IDC message.
145+
*/
146+
static inline void arch_idc_send_msg(void)
147+
{
148+
struct idc *idc = *idc_get();
149+
150+
struct idc_msg msg = idc->msg_to_send;
151+
int core = cpu_get_id();
152+
uint32_t flags;
153+
154+
tracev_idc("Msg");
155+
156+
spin_lock_irq(&idc->lock, flags);
157+
158+
idc_write(IPC_IDCIETC(msg.core), core, msg.extension);
159+
idc_write(IPC_IDCITC(msg.core), core, msg.header | IPC_IDCITC_BUSY);
160+
161+
spin_unlock_irq(&idc->lock, flags);
162+
}
163+
164+
/**
165+
* \brief Executes IDC message based on type.
166+
* \param[in,out] msg Pointer to IDC message.
167+
* \return Error status.
168+
*/
169+
static inline int32_t idc_cmd(struct idc_msg *msg)
170+
{
171+
/* execute message based on type */
172+
return 0;
173+
}
174+
175+
/**
176+
* \brief Handles received IDC message.
177+
* \param[in,out] idc Pointer to IDC data.
178+
*/
179+
static inline void idc_do_cmd(struct idc *idc)
180+
{
181+
int core = cpu_get_id();
182+
int initiator = idc->received_msg.core;
183+
184+
trace_idc("Cmd");
185+
186+
idc_cmd(&idc->received_msg);
187+
188+
idc->msg_pending = 0;
189+
190+
/* clear BUSY bit */
191+
idc_write(IPC_IDCTFC(initiator), core,
192+
idc_read(IPC_IDCTFC(initiator), core) | IPC_IDCTFC_BUSY);
193+
194+
/* enable BUSY interrupt */
195+
idc_write(IPC_IDCCTL, core, idc->busy_bit_mask | idc->done_bit_mask);
196+
}
197+
198+
/**
199+
* \brief Checks for pending IDC messages.
200+
*/
201+
static inline void arch_idc_process_msg_queue(void)
202+
{
203+
struct idc *idc = *idc_get();
204+
205+
if (idc->msg_pending)
206+
idc_do_cmd(idc);
207+
}
208+
209+
/**
210+
* \brief Returns BUSY interrupt mask based on core id.
211+
* \param[in] core Core id.
212+
* \return BUSY interrupt mask.
213+
*/
214+
static inline uint32_t idc_get_busy_bit_mask(int core)
215+
{
216+
uint32_t busy_mask = 0;
217+
int i;
218+
219+
if (core == PLATFORM_MASTER_CORE_ID) {
220+
for (i = 0; i < PLATFORM_CORE_COUNT; i++) {
221+
if (i != PLATFORM_MASTER_CORE_ID)
222+
busy_mask |= IPC_IDCCTL_IDCTBIE(i);
223+
}
224+
} else {
225+
busy_mask = IPC_IDCCTL_IDCTBIE(PLATFORM_MASTER_CORE_ID);
226+
}
227+
228+
return busy_mask;
229+
}
230+
231+
/**
232+
* \brief Returns DONE interrupt mask based on core id.
233+
* \param[in] core Core id.
234+
* \return DONE interrupt mask.
235+
*/
236+
static inline uint32_t idc_get_done_bit_mask(int core)
237+
{
238+
uint32_t done_mask = 0;
239+
int i;
240+
241+
if (core == PLATFORM_MASTER_CORE_ID) {
242+
for (i = 0; i < PLATFORM_CORE_COUNT; i++) {
243+
if (i != PLATFORM_MASTER_CORE_ID)
244+
done_mask |= IPC_IDCCTL_IDCIDIE(i);
245+
}
246+
} else {
247+
done_mask = 0;
248+
}
249+
250+
return done_mask;
251+
}
252+
253+
/**
254+
* \brief Initializes IDC data and registers for interrupt.
255+
*/
256+
static inline void arch_idc_init(void)
257+
{
258+
int core = cpu_get_id();
259+
260+
trace_idc("IDI");
261+
262+
/* initialize idc data */
263+
struct idc **idc = idc_get();
264+
*idc = rzalloc(RZONE_SYS, SOF_MEM_CAPS_RAM, sizeof(**idc));
265+
spinlock_init(&((*idc)->lock));
266+
(*idc)->busy_bit_mask = idc_get_busy_bit_mask(core);
267+
(*idc)->done_bit_mask = idc_get_done_bit_mask(core);
268+
269+
/* configure interrupt */
270+
interrupt_register(PLATFORM_IDC_INTERRUPT(core),
271+
idc_irq_handler, *idc);
272+
interrupt_enable(PLATFORM_IDC_INTERRUPT(core));
273+
274+
/* enable BUSY and DONE (only for master core) interrupts */
275+
idc_write(IPC_IDCCTL, core,
276+
(*idc)->busy_bit_mask | (*idc)->done_bit_mask);
277+
}
278+
279+
#endif

src/arch/xtensa/smp/schedule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
#include <arch/cpu.h>
4040
#include <sof/schedule.h>
4141

42-
struct schedule_data **arch_schedule_get()
42+
struct schedule_data **arch_schedule_get(void)
4343
{
4444
struct core_context *ctx = (struct core_context *)cpu_read_threadptr();
4545

src/arch/xtensa/smp/task.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,21 @@
3939
#include <arch/cpu.h>
4040
#include <arch/task.h>
4141

42-
struct irq_task **task_irq_low_get()
42+
struct irq_task **task_irq_low_get(void)
4343
{
4444
struct core_context *ctx = (struct core_context *)cpu_read_threadptr();
4545

4646
return &ctx->irq_low_task;
4747
}
4848

49-
struct irq_task **task_irq_med_get()
49+
struct irq_task **task_irq_med_get(void)
5050
{
5151
struct core_context *ctx = (struct core_context *)cpu_read_threadptr();
5252

5353
return &ctx->irq_med_task;
5454
}
5555

56-
struct irq_task **task_irq_high_get()
56+
struct irq_task **task_irq_high_get(void)
5757
{
5858
struct core_context *ctx = (struct core_context *)cpu_read_threadptr();
5959

src/arch/xtensa/smp/xtos/xtos-structs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#ifndef __XTOS_STRUCTS_H__
3434
#define __XTOS_STRUCTS_H__
3535

36+
struct idc;
3637
struct irq_task;
3738
struct schedule_data;
3839

@@ -56,6 +57,7 @@ struct core_context {
5657
struct irq_task *irq_med_task;
5758
struct irq_task *irq_high_task;
5859
struct schedule_data *sch;
60+
struct idc *idc;
5961
};
6062

6163
void _xtos_initialize_pointers_per_core(void);

src/arch/xtensa/up/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
SUBDIRS = hal xtos
1+
SUBDIRS = hal include xtos

0 commit comments

Comments
 (0)