ipi: rename to ipm
To many people, IPI connotes inter-processor interrupts on SMP systems. Rename this to IPM, or Inter-Processor Mailboxes. Change-Id: I032815e23c69a8297c0a43992132441c240fb71e Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
f6f81868f8
commit
3589695508
38 changed files with 614 additions and 596 deletions
|
@ -95,7 +95,7 @@ config KERNEL_INIT_PRIORITY_DEFAULT
|
|||
config KERNEL_INIT_PRIORITY_DEVICE
|
||||
default 50
|
||||
|
||||
config IPI_CONSOLE_PRIORITY
|
||||
config IPM_CONSOLE_PRIORITY
|
||||
default 60
|
||||
|
||||
config UART_CONSOLE_PRIORITY
|
||||
|
|
|
@ -18,40 +18,40 @@
|
|||
#include <init.h>
|
||||
#include "board.h"
|
||||
|
||||
#if CONFIG_IPI_QUARK_SE
|
||||
#include <ipi.h>
|
||||
#include <ipi/ipi_quark_se.h>
|
||||
#if CONFIG_IPM_QUARK_SE
|
||||
#include <ipm.h>
|
||||
#include <ipm/ipm_quark_se.h>
|
||||
|
||||
IRQ_CONNECT_STATIC(quark_se_ipi, QUARK_SE_IPI_INTERRUPT,
|
||||
QUARK_SE_IPI_INTERRUPT_PRI, quark_se_ipi_isr, NULL, 0);
|
||||
IRQ_CONNECT_STATIC(quark_se_ipm, QUARK_SE_IPM_INTERRUPT,
|
||||
QUARK_SE_IPM_INTERRUPT_PRI, quark_se_ipm_isr, NULL, 0);
|
||||
|
||||
static int arc_quark_se_ipi_init(void)
|
||||
static int arc_quark_se_ipm_init(void)
|
||||
{
|
||||
IRQ_CONFIG(quark_se_ipi, QUARK_SE_IPI_INTERRUPT);
|
||||
irq_enable(QUARK_SE_IPI_INTERRUPT);
|
||||
IRQ_CONFIG(quark_se_ipm, QUARK_SE_IPM_INTERRUPT);
|
||||
irq_enable(QUARK_SE_IPM_INTERRUPT);
|
||||
return DEV_OK;
|
||||
}
|
||||
|
||||
static struct quark_se_ipi_controller_config_info ipi_controller_config = {
|
||||
.controller_init = arc_quark_se_ipi_init
|
||||
static struct quark_se_ipm_controller_config_info ipm_controller_config = {
|
||||
.controller_init = arc_quark_se_ipm_init
|
||||
};
|
||||
DECLARE_DEVICE_INIT_CONFIG(quark_se_ipi, "", quark_se_ipi_controller_initialize,
|
||||
&ipi_controller_config);
|
||||
SYS_DEFINE_DEVICE(quark_se_ipi, NULL, SECONDARY,
|
||||
DECLARE_DEVICE_INIT_CONFIG(quark_se_ipm, "", quark_se_ipm_controller_initialize,
|
||||
&ipm_controller_config);
|
||||
SYS_DEFINE_DEVICE(quark_se_ipm, NULL, SECONDARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
|
||||
#if CONFIG_IPI_CONSOLE_SENDER
|
||||
#include <console/ipi_console.h>
|
||||
QUARK_SE_IPI_DEFINE(quark_se_ipi4, 4, QUARK_SE_IPI_OUTBOUND);
|
||||
#if CONFIG_IPM_CONSOLE_SENDER
|
||||
#include <console/ipm_console.h>
|
||||
QUARK_SE_IPM_DEFINE(quark_se_ipm4, 4, QUARK_SE_IPM_OUTBOUND);
|
||||
|
||||
struct ipi_console_sender_config_info quark_se_ipi_sender_config = {
|
||||
.bind_to = "quark_se_ipi4",
|
||||
.flags = IPI_CONSOLE_PRINTK | IPI_CONSOLE_STDOUT,
|
||||
struct ipm_console_sender_config_info quark_se_ipm_sender_config = {
|
||||
.bind_to = "quark_se_ipm4",
|
||||
.flags = IPM_CONSOLE_PRINTK | IPM_CONSOLE_STDOUT,
|
||||
};
|
||||
DECLARE_DEVICE_INIT_CONFIG(ipi_console, "ipi_console",
|
||||
ipi_console_sender_init,
|
||||
&quark_se_ipi_sender_config);
|
||||
SYS_DEFINE_DEVICE(ipi_console, NULL, SECONDARY, CONFIG_IPI_CONSOLE_PRIORITY);
|
||||
DECLARE_DEVICE_INIT_CONFIG(ipm_console, "ipm_console",
|
||||
ipm_console_sender_init,
|
||||
&quark_se_ipm_sender_config);
|
||||
SYS_DEFINE_DEVICE(ipm_console, NULL, SECONDARY, CONFIG_IPM_CONSOLE_PRIORITY);
|
||||
|
||||
#endif /* CONFIG_IPI_CONSOLE_SENDER */
|
||||
#endif /* CONFIG_IPI_QUARK_SE */
|
||||
#endif /* CONFIG_IPM_CONSOLE_SENDER */
|
||||
#endif /* CONFIG_IPM_QUARK_SE */
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <board.h>
|
||||
#include <init.h>
|
||||
#include <quark_se/shared_mem.h>
|
||||
#include <ipi/ipi_quark_se.h>
|
||||
|
||||
/* Cannot use microkernel, since only nanokernel is supported */
|
||||
#if defined(CONFIG_MICROKERNEL)
|
||||
|
|
|
@ -48,7 +48,7 @@ config KERNEL_INIT_PRIORITY_DEVICE
|
|||
config UART_CONSOLE_PRIORITY
|
||||
default 60
|
||||
|
||||
config IPI_CONSOLE_PRIORITY
|
||||
config IPM_CONSOLE_PRIORITY
|
||||
default 60
|
||||
|
||||
if UART_STELLARIS
|
||||
|
|
|
@ -47,7 +47,7 @@ config KERNEL_INIT_PRIORITY_DEVICE
|
|||
config UART_CONSOLE_PRIORITY
|
||||
default 60
|
||||
|
||||
config IPI_CONSOLE_PRIORITY
|
||||
config IPM_CONSOLE_PRIORITY
|
||||
default 60
|
||||
|
||||
if UART_NS16550
|
||||
|
|
|
@ -45,7 +45,7 @@ config KERNEL_INIT_PRIORITY_DEVICE
|
|||
config UART_CONSOLE_PRIORITY
|
||||
default 60
|
||||
|
||||
config IPI_CONSOLE_PRIORITY
|
||||
config IPM_CONSOLE_PRIORITY
|
||||
default 60
|
||||
|
||||
if UART_NS16550
|
||||
|
|
|
@ -202,7 +202,7 @@ config KERNEL_INIT_PRIORITY_DEVICE
|
|||
config UART_CONSOLE_PRIORITY
|
||||
default 60
|
||||
|
||||
config IPI_CONSOLE_PRIORITY
|
||||
config IPM_CONSOLE_PRIORITY
|
||||
default 60
|
||||
|
||||
config GPIO_DW_INIT_PRIORITY
|
||||
|
|
|
@ -23,55 +23,55 @@
|
|||
#include <nanokernel.h>
|
||||
#include <arch/cpu.h>
|
||||
|
||||
#if CONFIG_IPI_QUARK_SE
|
||||
#include <ipi.h>
|
||||
#include <ipi/ipi_quark_se.h>
|
||||
#if CONFIG_IPM_QUARK_SE
|
||||
#include <ipm.h>
|
||||
#include <ipm/ipm_quark_se.h>
|
||||
|
||||
IRQ_CONNECT_STATIC(quark_se_ipi, QUARK_SE_IPI_INTERRUPT, QUARK_SE_IPI_INTERRUPT_PRI,
|
||||
quark_se_ipi_isr, NULL, 0);
|
||||
IRQ_CONNECT_STATIC(quark_se_ipm, QUARK_SE_IPM_INTERRUPT, QUARK_SE_IPM_INTERRUPT_PRI,
|
||||
quark_se_ipm_isr, NULL, 0);
|
||||
|
||||
static int x86_quark_se_ipi_init(void)
|
||||
static int x86_quark_se_ipm_init(void)
|
||||
{
|
||||
IRQ_CONFIG(quark_se_ipi, QUARK_SE_IPI_INTERRUPT);
|
||||
irq_enable(QUARK_SE_IPI_INTERRUPT);
|
||||
IRQ_CONFIG(quark_se_ipm, QUARK_SE_IPM_INTERRUPT);
|
||||
irq_enable(QUARK_SE_IPM_INTERRUPT);
|
||||
return DEV_OK;
|
||||
}
|
||||
|
||||
static struct quark_se_ipi_controller_config_info ipi_controller_config = {
|
||||
.controller_init = x86_quark_se_ipi_init
|
||||
static struct quark_se_ipm_controller_config_info ipm_controller_config = {
|
||||
.controller_init = x86_quark_se_ipm_init
|
||||
};
|
||||
DECLARE_DEVICE_INIT_CONFIG(quark_se_ipi, "", quark_se_ipi_controller_initialize,
|
||||
&ipi_controller_config);
|
||||
SYS_DEFINE_DEVICE(quark_se_ipi, NULL, PRIMARY,
|
||||
DECLARE_DEVICE_INIT_CONFIG(quark_se_ipm, "", quark_se_ipm_controller_initialize,
|
||||
&ipm_controller_config);
|
||||
SYS_DEFINE_DEVICE(quark_se_ipm, NULL, PRIMARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
|
||||
|
||||
#if defined(CONFIG_IPI_CONSOLE_RECEIVER) && defined(CONFIG_PRINTK)
|
||||
#include <console/ipi_console.h>
|
||||
#if defined(CONFIG_IPM_CONSOLE_RECEIVER) && defined(CONFIG_PRINTK)
|
||||
#include <console/ipm_console.h>
|
||||
|
||||
QUARK_SE_IPI_DEFINE(quark_se_ipi4, 4, QUARK_SE_IPI_INBOUND);
|
||||
QUARK_SE_IPM_DEFINE(quark_se_ipm4, 4, QUARK_SE_IPM_INBOUND);
|
||||
|
||||
#define QUARK_SE_IPI_CONSOLE_LINE_BUF_SIZE 80
|
||||
#define QUARK_SE_IPI_CONSOLE_RING_BUF_SIZE32 128
|
||||
#define QUARK_SE_IPM_CONSOLE_LINE_BUF_SIZE 80
|
||||
#define QUARK_SE_IPM_CONSOLE_RING_BUF_SIZE32 128
|
||||
|
||||
static uint32_t ipi_console_ring_buf_data[QUARK_SE_IPI_CONSOLE_RING_BUF_SIZE32];
|
||||
static char __stack ipi_console_fiber_stack[IPI_CONSOLE_STACK_SIZE];
|
||||
static char ipi_console_line_buf[QUARK_SE_IPI_CONSOLE_LINE_BUF_SIZE];
|
||||
static uint32_t ipm_console_ring_buf_data[QUARK_SE_IPM_CONSOLE_RING_BUF_SIZE32];
|
||||
static char __stack ipm_console_fiber_stack[IPM_CONSOLE_STACK_SIZE];
|
||||
static char ipm_console_line_buf[QUARK_SE_IPM_CONSOLE_LINE_BUF_SIZE];
|
||||
|
||||
struct ipi_console_receiver_config_info quark_se_ipi_receiver_config = {
|
||||
.bind_to = "quark_se_ipi4",
|
||||
.fiber_stack = ipi_console_fiber_stack,
|
||||
.ring_buf_data = ipi_console_ring_buf_data,
|
||||
.rb_size32 = QUARK_SE_IPI_CONSOLE_RING_BUF_SIZE32,
|
||||
.line_buf = ipi_console_line_buf,
|
||||
.lb_size = QUARK_SE_IPI_CONSOLE_LINE_BUF_SIZE,
|
||||
.flags = IPI_CONSOLE_PRINTK
|
||||
struct ipm_console_receiver_config_info quark_se_ipm_receiver_config = {
|
||||
.bind_to = "quark_se_ipm4",
|
||||
.fiber_stack = ipm_console_fiber_stack,
|
||||
.ring_buf_data = ipm_console_ring_buf_data,
|
||||
.rb_size32 = QUARK_SE_IPM_CONSOLE_RING_BUF_SIZE32,
|
||||
.line_buf = ipm_console_line_buf,
|
||||
.lb_size = QUARK_SE_IPM_CONSOLE_LINE_BUF_SIZE,
|
||||
.flags = IPM_CONSOLE_PRINTK
|
||||
};
|
||||
struct ipi_console_receiver_runtime_data quark_se_ipi_receiver_driver_data;
|
||||
DECLARE_DEVICE_INIT_CONFIG(ipi_console0, "ipi_console0",
|
||||
ipi_console_receiver_init,
|
||||
&quark_se_ipi_receiver_config);
|
||||
SYS_DEFINE_DEVICE(ipi_console0, &quark_se_ipi_receiver_driver_data,
|
||||
SECONDARY, CONFIG_IPI_CONSOLE_PRIORITY);
|
||||
struct ipm_console_receiver_runtime_data quark_se_ipm_receiver_driver_data;
|
||||
DECLARE_DEVICE_INIT_CONFIG(ipm_console0, "ipm_console0",
|
||||
ipm_console_receiver_init,
|
||||
&quark_se_ipm_receiver_config);
|
||||
SYS_DEFINE_DEVICE(ipm_console0, &quark_se_ipm_receiver_driver_data,
|
||||
SECONDARY, CONFIG_IPM_CONSOLE_PRIORITY);
|
||||
|
||||
#endif /* CONFIG_PRINTK && CONFIG_IPI_CONSOLE_RECEIVER */
|
||||
#endif /* CONFIG_IPI_QUARK_SE */
|
||||
#endif /* CONFIG_PRINTK && CONFIG_IPM_CONSOLE_RECEIVER */
|
||||
#endif /* CONFIG_IPM_QUARK_SE */
|
||||
|
|
|
@ -8,10 +8,10 @@ CONFIG_SERIAL_INTERRUPT_LEVEL=n
|
|||
CONFIG_SERIAL_INTERRUPT_LOW=n
|
||||
CONFIG_UART_NS16550=y
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_IPI=y
|
||||
CONFIG_IPI_QUARK_SE=y
|
||||
CONFIG_IPI_QUARK_SE_MASTER=y
|
||||
CONFIG_IPI_CONSOLE_RECEIVER=y
|
||||
CONFIG_IPM=y
|
||||
CONFIG_IPM_QUARK_SE=y
|
||||
CONFIG_IPM_QUARK_SE_MASTER=y
|
||||
CONFIG_IPM_CONSOLE_RECEIVER=y
|
||||
CONFIG_ARC_INIT=y
|
||||
CONFIG_PINMUX=y
|
||||
CONFIG_PINMUX_NUM_PINS=58
|
||||
|
|
|
@ -8,8 +8,8 @@ CONFIG_SERIAL_INTERRUPT_LEVEL=n
|
|||
CONFIG_SERIAL_INTERRUPT_LOW=n
|
||||
CONFIG_UART_NS16550=y
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_IPI=y
|
||||
CONFIG_IPI_QUARK_SE=y
|
||||
CONFIG_IPI_QUARK_SE_MASTER=y
|
||||
CONFIG_IPI_CONSOLE_RECEIVER=y
|
||||
CONFIG_IPM=y
|
||||
CONFIG_IPM_QUARK_SE=y
|
||||
CONFIG_IPM_QUARK_SE_MASTER=y
|
||||
CONFIG_IPM_CONSOLE_RECEIVER=y
|
||||
CONFIG_ARC_INIT=y
|
||||
|
|
|
@ -9,7 +9,7 @@ CONFIG_CPU_ARCEM4=y
|
|||
CONFIG_CPU_ARCV2=y
|
||||
CONFIG_ARCV2_INTERRUPT_UNIT=y
|
||||
CONFIG_ARCV2_TIMER=y
|
||||
CONFIG_IPI=y
|
||||
CONFIG_IPI_QUARK_SE=y
|
||||
CONFIG_IPI_CONSOLE_SENDER=y
|
||||
CONFIG_IPM=y
|
||||
CONFIG_IPM_QUARK_SE=y
|
||||
CONFIG_IPM_CONSOLE_SENDER=y
|
||||
CONFIG_CONSOLE=y
|
||||
|
|
|
@ -57,7 +57,7 @@ source "drivers/watchdog/Kconfig"
|
|||
|
||||
source "drivers/clock_control/Kconfig"
|
||||
|
||||
source "drivers/ipi/Kconfig"
|
||||
source "drivers/ipm/Kconfig"
|
||||
|
||||
source "drivers/aio/Kconfig"
|
||||
|
||||
|
|
|
@ -20,5 +20,5 @@ obj-$(CONFIG_ETHERNET) += ethernet/
|
|||
obj-$(CONFIG_WATCHDOG) += watchdog/
|
||||
obj-$(CONFIG_RTC) += rtc/
|
||||
obj-$(CONFIG_CLOCK_CONTROL) += clock_control/
|
||||
obj-$(CONFIG_IPI) += ipi/
|
||||
obj-$(CONFIG_IPM) += ipm/
|
||||
obj-y += aio/
|
||||
|
|
|
@ -114,30 +114,30 @@ config RAM_CONSOLE_BUFFER_SIZE
|
|||
Size of the RAM console buffer. Messages will wrap around if the
|
||||
length is exceeded.
|
||||
|
||||
config IPI_CONSOLE_SENDER
|
||||
config IPM_CONSOLE_SENDER
|
||||
bool
|
||||
prompt "Inter-processor Interrupt console sender"
|
||||
prompt "Inter-processor Mailbox console sender"
|
||||
select CONSOLE_HAS_DRIVER
|
||||
default n
|
||||
help
|
||||
Enable the sending side of IPI console
|
||||
Enable the sending side of IPM console
|
||||
|
||||
config IPI_CONSOLE_RECEIVER
|
||||
config IPM_CONSOLE_RECEIVER
|
||||
bool
|
||||
prompt "Inter-processor interrupt console receiver"
|
||||
prompt "Inter-processor Mailbox console receiver"
|
||||
select RING_BUFFER
|
||||
default n
|
||||
help
|
||||
Enable the receiving side of IPI console
|
||||
Enable the receiving side of IPM console
|
||||
|
||||
config IPI_CONSOLE_PRIORITY
|
||||
config IPM_CONSOLE_PRIORITY
|
||||
int
|
||||
prompt "IPI console init priority"
|
||||
prompt "IPM console init priority"
|
||||
default 60
|
||||
depends on IPI_CONSOLE_SENDER || IPI_CONSOLE_RECEIVER
|
||||
depends on IPM_CONSOLE_SENDER || IPM_CONSOLE_RECEIVER
|
||||
help
|
||||
Device driver initialization priority.
|
||||
Console has to be initialized after the IPI subsystem
|
||||
Console has to be initialized after the IPM subsystem
|
||||
it uses.
|
||||
|
||||
config UART_PIPE
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
obj-$(CONFIG_CONSOLE_HANDLER_SHELL) += console_handler_shell.o
|
||||
obj-$(CONFIG_UART_CONSOLE) += uart_console.o uart_console_static_irq_stubs.o
|
||||
obj-$(CONFIG_RAM_CONSOLE) += ram_console.o
|
||||
obj-$(CONFIG_IPI_CONSOLE_RECEIVER) += ipi_console_receiver.o
|
||||
obj-$(CONFIG_IPI_CONSOLE_SENDER) += ipi_console_sender.o
|
||||
obj-$(CONFIG_IPM_CONSOLE_RECEIVER) += ipm_console_receiver.o
|
||||
obj-$(CONFIG_IPM_CONSOLE_SENDER) += ipm_console_sender.o
|
||||
obj-$(CONFIG_UART_PIPE) += uart_pipe.o uart_console_static_irq_stubs.o
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* ipi_console.c - Console messages to/from another processor */
|
||||
/* ipm_console.c - Console messages to/from another processor */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
|
@ -20,17 +20,17 @@
|
|||
#include <misc/ring_buffer.h>
|
||||
#include <misc/printk.h>
|
||||
#include <stdio.h>
|
||||
#include <ipi.h>
|
||||
#include <console/ipi_console.h>
|
||||
#include <ipm.h>
|
||||
#include <console/ipm_console.h>
|
||||
|
||||
static void ipi_console_fiber(int arg1, int arg2)
|
||||
static void ipm_console_fiber(int arg1, int arg2)
|
||||
{
|
||||
uint8_t size32;
|
||||
uint16_t type;
|
||||
int ret;
|
||||
struct device *d;
|
||||
struct ipi_console_receiver_config_info *config_info;
|
||||
struct ipi_console_receiver_runtime_data *driver_data;
|
||||
struct ipm_console_receiver_config_info *config_info;
|
||||
struct ipm_console_receiver_runtime_data *driver_data;
|
||||
int pos;
|
||||
|
||||
d = (struct device *)arg1;
|
||||
|
@ -48,7 +48,7 @@ static void ipi_console_fiber(int arg1, int arg2)
|
|||
NULL, &size32);
|
||||
if (ret) {
|
||||
/* Shouldn't ever happen... */
|
||||
printk("ipi console ring buffer error: %d\n", ret);
|
||||
printk("ipm console ring buffer error: %d\n", ret);
|
||||
size32 = 0;
|
||||
continue;
|
||||
}
|
||||
|
@ -60,11 +60,11 @@ static void ipi_console_fiber(int arg1, int arg2)
|
|||
} else {
|
||||
config_info->line_buf[pos + 1] = '\0';
|
||||
}
|
||||
if (config_info->flags & IPI_CONSOLE_PRINTK) {
|
||||
if (config_info->flags & IPM_CONSOLE_PRINTK) {
|
||||
printk("%s: '%s'\n", d->config->name,
|
||||
config_info->line_buf);
|
||||
}
|
||||
if (config_info->flags & IPI_CONSOLE_STDOUT) {
|
||||
if (config_info->flags & IPM_CONSOLE_STDOUT) {
|
||||
printf("%s: '%s'\n", d->config->name,
|
||||
config_info->line_buf);
|
||||
}
|
||||
|
@ -75,11 +75,11 @@ static void ipi_console_fiber(int arg1, int arg2)
|
|||
}
|
||||
}
|
||||
|
||||
static void ipi_console_receive_callback(void *context, uint32_t id,
|
||||
static void ipm_console_receive_callback(void *context, uint32_t id,
|
||||
volatile void *data)
|
||||
{
|
||||
struct device *d;
|
||||
struct ipi_console_receiver_runtime_data *driver_data;
|
||||
struct ipm_console_receiver_runtime_data *driver_data;
|
||||
|
||||
ARG_UNUSED(data);
|
||||
d = context;
|
||||
|
@ -90,23 +90,23 @@ static void ipi_console_receive_callback(void *context, uint32_t id,
|
|||
}
|
||||
|
||||
|
||||
int ipi_console_receiver_init(struct device *d)
|
||||
int ipm_console_receiver_init(struct device *d)
|
||||
{
|
||||
struct ipi_console_receiver_config_info *config_info =
|
||||
struct ipm_console_receiver_config_info *config_info =
|
||||
d->config->config_info;
|
||||
struct ipi_console_receiver_runtime_data *driver_data = d->driver_data;
|
||||
struct device *ipi;
|
||||
struct ipm_console_receiver_runtime_data *driver_data = d->driver_data;
|
||||
struct device *ipm;
|
||||
|
||||
ipi = device_get_binding(config_info->bind_to);
|
||||
ipm = device_get_binding(config_info->bind_to);
|
||||
|
||||
if (!ipi) {
|
||||
printk("unable to bind IPI console receiver to '%s'\n",
|
||||
if (!ipm) {
|
||||
printk("unable to bind IPM console receiver to '%s'\n",
|
||||
__func__, config_info->bind_to);
|
||||
return DEV_INVALID_CONF;
|
||||
}
|
||||
|
||||
if (ipi_max_id_val_get(ipi) < 0xFF) {
|
||||
printk("IPI driver %s doesn't support 8-bit id values",
|
||||
if (ipm_max_id_val_get(ipm) < 0xFF) {
|
||||
printk("IPM driver %s doesn't support 8-bit id values",
|
||||
config_info->bind_to);
|
||||
return DEV_INVALID_CONF;
|
||||
}
|
||||
|
@ -115,12 +115,12 @@ int ipi_console_receiver_init(struct device *d)
|
|||
sys_ring_buf_init(&driver_data->rb, config_info->rb_size32,
|
||||
config_info->ring_buf_data);
|
||||
|
||||
ipi_register_callback(ipi, ipi_console_receive_callback, d);
|
||||
ipm_register_callback(ipm, ipm_console_receive_callback, d);
|
||||
|
||||
task_fiber_start(config_info->fiber_stack, IPI_CONSOLE_STACK_SIZE,
|
||||
ipi_console_fiber, (int)d, 0,
|
||||
IPI_CONSOLE_PRI, 0);
|
||||
ipi_set_enabled(ipi, 1);
|
||||
task_fiber_start(config_info->fiber_stack, IPM_CONSOLE_STACK_SIZE,
|
||||
ipm_console_fiber, (int)d, 0,
|
||||
IPM_CONSOLE_PRI, 0);
|
||||
ipm_set_enabled(ipm, 1);
|
||||
|
||||
return DEV_OK;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* ipi_console_send.c - Console messages to another processor */
|
||||
/* ipm_console_send.c - Console messages to another processor */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
|
@ -18,10 +18,10 @@
|
|||
|
||||
#include <nanokernel.h>
|
||||
#include <misc/printk.h>
|
||||
#include <ipi.h>
|
||||
#include <console/ipi_console.h>
|
||||
#include <ipm.h>
|
||||
#include <console/ipm_console.h>
|
||||
|
||||
static struct device *ipi_console_device;
|
||||
static struct device *ipm_console_device;
|
||||
|
||||
static int consoleOut(int character)
|
||||
{
|
||||
|
@ -33,7 +33,7 @@ static int consoleOut(int character)
|
|||
* We just stash the character into the id field and don't supply
|
||||
* any extra data
|
||||
*/
|
||||
ipi_send(ipi_console_device, 1, character, NULL, 0);
|
||||
ipm_send(ipm_console_device, 1, character, NULL, 0);
|
||||
|
||||
return character;
|
||||
}
|
||||
|
@ -41,23 +41,23 @@ static int consoleOut(int character)
|
|||
extern void __printk_hook_install(int (*fn)(int));
|
||||
extern void __stdout_hook_install(int (*fn)(int));
|
||||
|
||||
int ipi_console_sender_init(struct device *d)
|
||||
int ipm_console_sender_init(struct device *d)
|
||||
{
|
||||
struct ipi_console_sender_config_info *config_info;
|
||||
struct ipm_console_sender_config_info *config_info;
|
||||
|
||||
config_info = d->config->config_info;
|
||||
ipi_console_device = device_get_binding(config_info->bind_to);
|
||||
ipm_console_device = device_get_binding(config_info->bind_to);
|
||||
|
||||
if (!ipi_console_device) {
|
||||
printk("unable to bind IPI console sender to '%s'\n",
|
||||
if (!ipm_console_device) {
|
||||
printk("unable to bind IPM console sender to '%s'\n",
|
||||
config_info->bind_to);
|
||||
return DEV_INVALID_CONF;
|
||||
}
|
||||
|
||||
if (config_info->flags & IPI_CONSOLE_STDOUT) {
|
||||
if (config_info->flags & IPM_CONSOLE_STDOUT) {
|
||||
__stdout_hook_install(consoleOut);
|
||||
}
|
||||
if (config_info->flags & IPI_CONSOLE_PRINTK) {
|
||||
if (config_info->flags & IPM_CONSOLE_PRINTK) {
|
||||
__printk_hook_install(consoleOut);
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
menuconfig IPI
|
||||
bool
|
||||
prompt "IPI drivers"
|
||||
default n
|
||||
help
|
||||
Include interrupt-based inter-processor communication
|
||||
drivers in system configuration
|
||||
|
||||
config IPI_QUARK_SE
|
||||
bool "Quark SE Mailbox IPI driver"
|
||||
default n
|
||||
depends on IPI
|
||||
help
|
||||
IPI driver for Quark SE mailboxes
|
||||
|
||||
config IPI_QUARK_SE_MASTER
|
||||
bool "Quark SE Mailbox IPI master controller"
|
||||
default n
|
||||
depends on IPI_QUARK_SE
|
||||
help
|
||||
Enable this for the first CPU that initializes IPI.
|
||||
Sets up the initial interrupt mask and clears out all
|
||||
channels. Should be turned on for one CPU only.
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
ccflags-y += -I$(srctree/drivers)
|
||||
|
||||
obj-$(CONFIG_IPI_QUARK_SE) += ipi_quark_se.o ipi_static_irq_stubs.o
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
/* ipi_quark_se.h - Quark SE mailbox driver */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __INCquark_se_mailboxh
|
||||
#define __INCquark_se_mailboxh
|
||||
|
||||
#include <nanokernel.h>
|
||||
#include <board.h> /* for SCSS_REGISTER_BASE */
|
||||
#include <ipi.h>
|
||||
#include <device.h>
|
||||
#include <init.h>
|
||||
|
||||
#define QUARK_SE_IPI_OUTBOUND 0
|
||||
#define QUARK_SE_IPI_INBOUND 1
|
||||
|
||||
#if defined(CONFIG_PLATFORM_QUARK_SE)
|
||||
/* First byte of the QUARK_SE_IPI_MASK register is for the Lakemont */
|
||||
#define QUARK_SE_IPI_MASK_START_BIT 0
|
||||
#define QUARK_SE_IPI_INTERRUPT 21
|
||||
#define QUARK_SE_IPI_ARC_LMT_DIR QUARK_SE_IPI_INBOUND
|
||||
#define QUARK_SE_IPI_LMT_ARC_DIR QUARK_SE_IPI_OUTBOUND
|
||||
|
||||
#elif defined(CONFIG_PLATFORM_QUARK_SE_SS)
|
||||
/* Second byte is for ARC */
|
||||
#define QUARK_SE_IPI_MASK_START_BIT 8
|
||||
#define QUARK_SE_IPI_INTERRUPT 57
|
||||
#define QUARK_SE_IPI_ARC_LMT_DIR QUARK_SE_IPI_OUTBOUND
|
||||
#define QUARK_SE_IPI_LMT_ARC_DIR QUARK_SE_IPI_INBOUND
|
||||
|
||||
#else
|
||||
#error "Unsupported platform for ipi_quark_se driver"
|
||||
#endif
|
||||
|
||||
#define QUARK_SE_IPI_CHANNELS 8
|
||||
#define QUARK_SE_IPI_DATA_BYTES (4 * sizeof(uint32_t))
|
||||
#define QUARK_SE_IPI_MAX_ID_VAL 0x7FFFFFFF
|
||||
|
||||
/* QUARK_SE EAS section 28.5.1.123 */
|
||||
struct __packed quark_se_ipi_ch_ctrl {
|
||||
uint32_t ctrl : 31;
|
||||
uint32_t irq : 1;
|
||||
};
|
||||
|
||||
struct __packed quark_se_ipi_ch_sts {
|
||||
uint32_t sts : 1;
|
||||
uint32_t irq : 1;
|
||||
uint32_t reserved : 30;
|
||||
};
|
||||
|
||||
struct __packed quark_se_ipi {
|
||||
struct quark_se_ipi_ch_ctrl ctrl;
|
||||
uint8_t data[QUARK_SE_IPI_DATA_BYTES]; /* contiguous 32-bit registers */
|
||||
struct quark_se_ipi_ch_sts sts;
|
||||
};
|
||||
|
||||
/* Base address for mailboxes
|
||||
*
|
||||
* Layout:
|
||||
*
|
||||
* quark_se_ipi[8]
|
||||
* QUARK_SE_IPI_CHALL_STS
|
||||
*/
|
||||
#define QUARK_SE_IPI_BASE (SCSS_REGISTER_BASE + 0xa00)
|
||||
|
||||
/* 28.5.1.73 Host processor Interrupt routing mask 21
|
||||
*
|
||||
* Bits Description
|
||||
* 31:24 Mailbox SS Halt interrupt maskIUL
|
||||
* 23:16 Mailbox Host Halt interrupt mask
|
||||
* 15:8 Mailbox SS interrupt mask
|
||||
* 7:0 Mailbox Host interrupt mask
|
||||
*/
|
||||
#define QUARK_SE_IPI_MASK (SCSS_REGISTER_BASE + 0x4a0)
|
||||
|
||||
/* All status bits of the mailboxes
|
||||
*
|
||||
* Bits Description
|
||||
* 31:16 Reserved
|
||||
* 15:0 CHn_STS bits (sts/irq) for all channels
|
||||
*/
|
||||
#define QUARK_SE_IPI_CHALL_STS (SCSS_REGISTER_BASE + 0x0AC0)
|
||||
|
||||
#define QUARK_SE_IPI(channel) ((volatile struct quark_se_ipi *)(QUARK_SE_IPI_BASE + \
|
||||
((channel) * sizeof(struct quark_se_ipi))))
|
||||
|
||||
|
||||
/* XXX I pulled this number out of thin air -- how to choose
|
||||
* the right priority? */
|
||||
#define QUARK_SE_IPI_INTERRUPT_PRI 2
|
||||
|
||||
struct quark_se_ipi_controller_config_info {
|
||||
int (*controller_init)(void);
|
||||
};
|
||||
|
||||
struct quark_se_ipi_config_info {
|
||||
int channel;
|
||||
int direction;
|
||||
volatile struct quark_se_ipi *ipi;
|
||||
};
|
||||
|
||||
|
||||
struct quark_se_ipi_driver_data {
|
||||
ipi_callback_t callback;
|
||||
void *callback_ctx;
|
||||
};
|
||||
|
||||
void quark_se_ipi_isr(void *param);
|
||||
|
||||
int quark_se_ipi_initialize(struct device *d);
|
||||
int quark_se_ipi_controller_initialize(struct device *d);
|
||||
|
||||
#define QUARK_SE_IPI_DEFINE(name, ch, dir) \
|
||||
struct quark_se_ipi_config_info quark_se_ipi_config_##name = { \
|
||||
.ipi = QUARK_SE_IPI(ch), \
|
||||
.channel = ch, \
|
||||
.direction = dir \
|
||||
}; \
|
||||
struct quark_se_ipi_driver_data quark_se_ipi_runtime_##name; \
|
||||
DECLARE_DEVICE_INIT_CONFIG(name, _STRINGIFY(name), \
|
||||
quark_se_ipi_initialize, \
|
||||
&quark_se_ipi_config_##name); \
|
||||
SYS_DEFINE_DEVICE(name, &quark_se_ipi_runtime_##name, SECONDARY, \
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
|
||||
|
||||
#endif /* __INCquark_se_mailboxh */
|
24
drivers/ipm/Kconfig
Normal file
24
drivers/ipm/Kconfig
Normal file
|
@ -0,0 +1,24 @@
|
|||
menuconfig IPM
|
||||
bool
|
||||
prompt "IPM drivers"
|
||||
default n
|
||||
help
|
||||
Include interrupt-based inter-processor mailboxes
|
||||
drivers in system configuration
|
||||
|
||||
config IPM_QUARK_SE
|
||||
bool "Quark SE IPM driver"
|
||||
default n
|
||||
depends on IPM
|
||||
help
|
||||
Driver for Quark SE mailboxes
|
||||
|
||||
config IPM_QUARK_SE_MASTER
|
||||
bool "Quark SE IPM master controller"
|
||||
default n
|
||||
depends on IPM_QUARK_SE
|
||||
help
|
||||
Enable this for the first CPU that initializes IPM.
|
||||
Sets up the initial interrupt mask and clears out all
|
||||
channels. Should be turned on for one CPU only.
|
||||
|
4
drivers/ipm/Makefile
Normal file
4
drivers/ipm/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
ccflags-y += -I$(srctree/drivers)
|
||||
|
||||
obj-$(CONFIG_IPM_QUARK_SE) += ipm_quark_se.o ipm_static_irq_stubs.o
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
/* ipi_quark_se.c - Quark SE mailbox driver */
|
||||
/* ipm_quark_se.c - Quark SE mailbox driver */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
|
@ -21,49 +21,50 @@
|
|||
#include <string.h>
|
||||
#include <device.h>
|
||||
#include <init.h>
|
||||
#include <ipi.h>
|
||||
#include <ipm.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <misc/printk.h>
|
||||
#include <misc/__assert.h>
|
||||
#include <errno.h>
|
||||
#include "ipi_quark_se.h"
|
||||
#include "ipm_quark_se.h"
|
||||
|
||||
|
||||
/* We have a single ISR for all channels, so in order to properly handle
|
||||
* messages we need to figure out which device object corresponds to
|
||||
* in incoming channel */
|
||||
static struct device *device_by_channel[QUARK_SE_IPI_CHANNELS];
|
||||
* in incoming channel
|
||||
*/
|
||||
static struct device *device_by_channel[QUARK_SE_IPM_CHANNELS];
|
||||
static uint32_t inbound_channels;
|
||||
|
||||
static uint32_t quark_se_ipi_sts_get(void)
|
||||
static uint32_t quark_se_ipm_sts_get(void)
|
||||
{
|
||||
return sys_read32(QUARK_SE_IPI_CHALL_STS) & inbound_channels;
|
||||
return sys_read32(QUARK_SE_IPM_CHALL_STS) & inbound_channels;
|
||||
}
|
||||
|
||||
static void mailbox_handle(struct device *d)
|
||||
{
|
||||
struct quark_se_ipi_config_info *config;
|
||||
struct quark_se_ipi_driver_data *driver_data;
|
||||
volatile struct quark_se_ipi *ipi;
|
||||
struct quark_se_ipm_config_info *config;
|
||||
struct quark_se_ipm_driver_data *driver_data;
|
||||
volatile struct quark_se_ipm *ipm;
|
||||
|
||||
config = d->config->config_info;
|
||||
driver_data = d->driver_data;
|
||||
ipi = config->ipi;
|
||||
ipm = config->ipm;
|
||||
|
||||
if (driver_data->callback) {
|
||||
driver_data->callback(driver_data->callback_ctx,
|
||||
ipi->ctrl.ctrl, &ipi->data);
|
||||
ipm->ctrl.ctrl, &ipm->data);
|
||||
}
|
||||
|
||||
ipi->sts.irq = 1; /* Clear the interrupt bit */
|
||||
ipi->sts.sts = 1; /* Clear channel status bit */
|
||||
ipm->sts.irq = 1; /* Clear the interrupt bit */
|
||||
ipm->sts.sts = 1; /* Clear channel status bit */
|
||||
}
|
||||
|
||||
|
||||
static void set_channel_irq_state(int channel, int enable)
|
||||
{
|
||||
mem_addr_t addr = QUARK_SE_IPI_MASK;
|
||||
int bit = channel + QUARK_SE_IPI_MASK_START_BIT;
|
||||
mem_addr_t addr = QUARK_SE_IPM_MASK;
|
||||
int bit = channel + QUARK_SE_IPM_MASK_START_BIT;
|
||||
|
||||
if (enable) {
|
||||
sys_clear_bit(addr, bit);
|
||||
|
@ -74,7 +75,7 @@ static void set_channel_irq_state(int channel, int enable)
|
|||
|
||||
|
||||
/* Interrupt handler, gets messages on all incoming enabled mailboxes */
|
||||
void quark_se_ipi_isr(void *param)
|
||||
void quark_se_ipm_isr(void *param)
|
||||
{
|
||||
int channel;
|
||||
int sts;
|
||||
|
@ -84,11 +85,12 @@ void quark_se_ipi_isr(void *param)
|
|||
|
||||
/* Find out which mailbox channel has an incoming message */
|
||||
while (1) {
|
||||
sts = quark_se_ipi_sts_get();
|
||||
sts = quark_se_ipm_sts_get();
|
||||
|
||||
/* FIXME: for every message sent, there are two interrupts
|
||||
* generated, the second has empty sts. Probably an IRQ
|
||||
* triggering issue */
|
||||
* triggering issue
|
||||
*/
|
||||
if (!sts) {
|
||||
break;
|
||||
}
|
||||
|
@ -103,30 +105,30 @@ void quark_se_ipi_isr(void *param)
|
|||
}
|
||||
|
||||
|
||||
static int quark_se_ipi_send(struct device *d, int wait, uint32_t id,
|
||||
static int quark_se_ipm_send(struct device *d, int wait, uint32_t id,
|
||||
const void *data, int size)
|
||||
{
|
||||
struct quark_se_ipi_config_info *config = d->config->config_info;
|
||||
volatile struct quark_se_ipi *ipi = config->ipi;
|
||||
struct quark_se_ipm_config_info *config = d->config->config_info;
|
||||
volatile struct quark_se_ipm *ipm = config->ipm;
|
||||
const uint8_t *data8;
|
||||
int i;
|
||||
int flags;
|
||||
|
||||
if (id > QUARK_SE_IPI_MAX_ID_VAL) {
|
||||
if (id > QUARK_SE_IPM_MAX_ID_VAL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (config->direction != QUARK_SE_IPI_OUTBOUND) {
|
||||
if (config->direction != QUARK_SE_IPM_OUTBOUND) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (size > QUARK_SE_IPI_DATA_BYTES) {
|
||||
if (size > QUARK_SE_IPM_DATA_BYTES) {
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
flags = irq_lock();
|
||||
|
||||
if (ipi->sts.sts != 0) {
|
||||
if (ipm->sts.sts != 0) {
|
||||
irq_unlock(flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
@ -135,20 +137,20 @@ static int quark_se_ipi_send(struct device *d, int wait, uint32_t id,
|
|||
data8 = (const uint8_t *)data;
|
||||
|
||||
for (i = 0; i < size; ++i) {
|
||||
ipi->data[i] = data8[i];
|
||||
ipm->data[i] = data8[i];
|
||||
}
|
||||
ipi->ctrl.ctrl = id;
|
||||
ipm->ctrl.ctrl = id;
|
||||
|
||||
/* Cause the interrupt to assert on the remote side */
|
||||
ipi->ctrl.irq = 1;
|
||||
ipm->ctrl.irq = 1;
|
||||
|
||||
/* Wait for HW to set the sts bit */
|
||||
while (ipi->sts.sts == 0) {
|
||||
while (ipm->sts.sts == 0) {
|
||||
}
|
||||
|
||||
if (wait) {
|
||||
/* Loop until remote clears the status bit */
|
||||
while (ipi->sts.sts != 0) {
|
||||
while (ipm->sts.sts != 0) {
|
||||
}
|
||||
}
|
||||
irq_unlock(flags);
|
||||
|
@ -156,63 +158,65 @@ static int quark_se_ipi_send(struct device *d, int wait, uint32_t id,
|
|||
}
|
||||
|
||||
|
||||
static int quark_se_ipi_max_data_size_get(struct device *d)
|
||||
static int quark_se_ipm_max_data_size_get(struct device *d)
|
||||
{
|
||||
ARG_UNUSED(d);
|
||||
|
||||
return QUARK_SE_IPI_DATA_BYTES;
|
||||
return QUARK_SE_IPM_DATA_BYTES;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t quark_se_ipi_max_id_val_get(struct device *d)
|
||||
static uint32_t quark_se_ipm_max_id_val_get(struct device *d)
|
||||
{
|
||||
ARG_UNUSED(d);
|
||||
|
||||
return QUARK_SE_IPI_MAX_ID_VAL;
|
||||
return QUARK_SE_IPM_MAX_ID_VAL;
|
||||
}
|
||||
|
||||
static void quark_se_ipi_register_callback(struct device *d, ipi_callback_t cb,
|
||||
static void quark_se_ipm_register_callback(struct device *d, ipm_callback_t cb,
|
||||
void *context)
|
||||
{
|
||||
struct quark_se_ipi_driver_data *driver_data = d->driver_data;
|
||||
struct quark_se_ipm_driver_data *driver_data = d->driver_data;
|
||||
|
||||
driver_data->callback = cb;
|
||||
driver_data->callback_ctx = context;
|
||||
}
|
||||
|
||||
|
||||
static int quark_se_ipi_set_enabled(struct device *d, int enable)
|
||||
static int quark_se_ipm_set_enabled(struct device *d, int enable)
|
||||
{
|
||||
struct quark_se_ipi_config_info *config_info = d->config->config_info;
|
||||
struct quark_se_ipm_config_info *config_info = d->config->config_info;
|
||||
|
||||
if (config_info->direction != QUARK_SE_IPI_INBOUND) {
|
||||
if (config_info->direction != QUARK_SE_IPM_INBOUND) {
|
||||
return -EINVAL;
|
||||
}
|
||||
set_channel_irq_state(config_info->channel, enable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ipi_driver_api api_funcs = {
|
||||
.send = quark_se_ipi_send,
|
||||
.register_callback = quark_se_ipi_register_callback,
|
||||
.max_data_size_get = quark_se_ipi_max_data_size_get,
|
||||
.max_id_val_get = quark_se_ipi_max_id_val_get,
|
||||
.set_enabled = quark_se_ipi_set_enabled
|
||||
static struct ipm_driver_api api_funcs = {
|
||||
.send = quark_se_ipm_send,
|
||||
.register_callback = quark_se_ipm_register_callback,
|
||||
.max_data_size_get = quark_se_ipm_max_data_size_get,
|
||||
.max_id_val_get = quark_se_ipm_max_id_val_get,
|
||||
.set_enabled = quark_se_ipm_set_enabled
|
||||
};
|
||||
|
||||
int quark_se_ipi_controller_initialize(struct device *d)
|
||||
int quark_se_ipm_controller_initialize(struct device *d)
|
||||
{
|
||||
struct quark_se_ipi_controller_config_info *config = d->config->config_info;
|
||||
#if CONFIG_IPI_QUARK_SE_MASTER
|
||||
struct quark_se_ipm_controller_config_info *config = d->config->config_info;
|
||||
#if CONFIG_IPM_QUARK_SE_MASTER
|
||||
int i;
|
||||
|
||||
/* Mask all mailbox interrupts, we'll enable them
|
||||
* individually later. Clear out any pending messages */
|
||||
sys_write32(0xFFFFFFFF, QUARK_SE_IPI_MASK);
|
||||
for (i = 0; i < QUARK_SE_IPI_CHANNELS; ++i) {
|
||||
volatile struct quark_se_ipi *ipi = QUARK_SE_IPI(i);
|
||||
ipi->sts.sts = 0;
|
||||
ipi->sts.irq = 0;
|
||||
* individually later. Clear out any pending messages
|
||||
*/
|
||||
sys_write32(0xFFFFFFFF, QUARK_SE_IPM_MASK);
|
||||
for (i = 0; i < QUARK_SE_IPM_CHANNELS; ++i) {
|
||||
volatile struct quark_se_ipm *ipm = QUARK_SE_IPM(i);
|
||||
|
||||
ipm->sts.sts = 0;
|
||||
ipm->sts.irq = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -223,13 +227,13 @@ int quark_se_ipi_controller_initialize(struct device *d)
|
|||
}
|
||||
|
||||
|
||||
int quark_se_ipi_initialize(struct device *d)
|
||||
int quark_se_ipm_initialize(struct device *d)
|
||||
{
|
||||
struct quark_se_ipi_config_info *config = d->config->config_info;
|
||||
struct quark_se_ipm_config_info *config = d->config->config_info;
|
||||
|
||||
device_by_channel[config->channel] = d;
|
||||
d->driver_api = &api_funcs;
|
||||
if (config->direction == QUARK_SE_IPI_INBOUND) {
|
||||
if (config->direction == QUARK_SE_IPM_INBOUND) {
|
||||
inbound_channels |= (0x3 << (config->channel * 2));
|
||||
}
|
||||
|
143
drivers/ipm/ipm_quark_se.h
Normal file
143
drivers/ipm/ipm_quark_se.h
Normal file
|
@ -0,0 +1,143 @@
|
|||
/* ipm_quark_se.h - Quark SE mailbox driver */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __INCquark_se_mailboxh
|
||||
#define __INCquark_se_mailboxh
|
||||
|
||||
#include <nanokernel.h>
|
||||
#include <board.h> /* for SCSS_REGISTER_BASE */
|
||||
#include <ipm.h>
|
||||
#include <device.h>
|
||||
#include <init.h>
|
||||
|
||||
#define QUARK_SE_IPM_OUTBOUND 0
|
||||
#define QUARK_SE_IPM_INBOUND 1
|
||||
|
||||
#if defined(CONFIG_PLATFORM_QUARK_SE)
|
||||
/* First byte of the QUARK_SE_IPM_MASK register is for the Lakemont */
|
||||
#define QUARK_SE_IPM_MASK_START_BIT 0
|
||||
#define QUARK_SE_IPM_INTERRUPT 21
|
||||
#define QUARK_SE_IPM_ARC_LMT_DIR QUARK_SE_IPM_INBOUND
|
||||
#define QUARK_SE_IPM_LMT_ARC_DIR QUARK_SE_IPM_OUTBOUND
|
||||
|
||||
#elif defined(CONFIG_PLATFORM_QUARK_SE_SS)
|
||||
/* Second byte is for ARC */
|
||||
#define QUARK_SE_IPM_MASK_START_BIT 8
|
||||
#define QUARK_SE_IPM_INTERRUPT 57
|
||||
#define QUARK_SE_IPM_ARC_LMT_DIR QUARK_SE_IPM_OUTBOUND
|
||||
#define QUARK_SE_IPM_LMT_ARC_DIR QUARK_SE_IPM_INBOUND
|
||||
|
||||
#else
|
||||
#error "Unsupported platform for ipm_quark_se driver"
|
||||
#endif
|
||||
|
||||
#define QUARK_SE_IPM_CHANNELS 8
|
||||
#define QUARK_SE_IPM_DATA_BYTES (4 * sizeof(uint32_t))
|
||||
#define QUARK_SE_IPM_MAX_ID_VAL 0x7FFFFFFF
|
||||
|
||||
/* QUARK_SE EAS section 28.5.1.123 */
|
||||
struct __packed quark_se_ipm_ch_ctrl {
|
||||
uint32_t ctrl : 31;
|
||||
uint32_t irq : 1;
|
||||
};
|
||||
|
||||
struct __packed quark_se_ipm_ch_sts {
|
||||
uint32_t sts : 1;
|
||||
uint32_t irq : 1;
|
||||
uint32_t reserved : 30;
|
||||
};
|
||||
|
||||
struct __packed quark_se_ipm {
|
||||
struct quark_se_ipm_ch_ctrl ctrl;
|
||||
uint8_t data[QUARK_SE_IPM_DATA_BYTES]; /* contiguous 32-bit registers */
|
||||
struct quark_se_ipm_ch_sts sts;
|
||||
};
|
||||
|
||||
/* Base address for mailboxes
|
||||
*
|
||||
* Layout:
|
||||
*
|
||||
* quark_se_ipm[8]
|
||||
* QUARK_SE_IPM_CHALL_STS
|
||||
*/
|
||||
#define QUARK_SE_IPM_BASE (SCSS_REGISTER_BASE + 0xa00)
|
||||
|
||||
/* 28.5.1.73 Host processor Interrupt routing mask 21
|
||||
*
|
||||
* Bits Description
|
||||
* 31:24 Mailbox SS Halt interrupt maskIUL
|
||||
* 23:16 Mailbox Host Halt interrupt mask
|
||||
* 15:8 Mailbox SS interrupt mask
|
||||
* 7:0 Mailbox Host interrupt mask
|
||||
*/
|
||||
#define QUARK_SE_IPM_MASK (SCSS_REGISTER_BASE + 0x4a0)
|
||||
|
||||
/* All status bits of the mailboxes
|
||||
*
|
||||
* Bits Description
|
||||
* 31:16 Reserved
|
||||
* 15:0 CHn_STS bits (sts/irq) for all channels
|
||||
*/
|
||||
#define QUARK_SE_IPM_CHALL_STS (SCSS_REGISTER_BASE + 0x0AC0)
|
||||
|
||||
#define QUARK_SE_IPM(channel) ((volatile struct quark_se_ipm *)(QUARK_SE_IPM_BASE + \
|
||||
((channel) * sizeof(struct quark_se_ipm))))
|
||||
|
||||
|
||||
/* XXX I pulled this number out of thin air -- how to choose
|
||||
* the right priority?
|
||||
*/
|
||||
#define QUARK_SE_IPM_INTERRUPT_PRI 2
|
||||
|
||||
struct quark_se_ipm_controller_config_info {
|
||||
int (*controller_init)(void);
|
||||
};
|
||||
|
||||
struct quark_se_ipm_config_info {
|
||||
int channel;
|
||||
int direction;
|
||||
volatile struct quark_se_ipm *ipm;
|
||||
};
|
||||
|
||||
|
||||
struct quark_se_ipm_driver_data {
|
||||
ipm_callback_t callback;
|
||||
void *callback_ctx;
|
||||
};
|
||||
|
||||
void quark_se_ipm_isr(void *param);
|
||||
|
||||
int quark_se_ipm_initialize(struct device *d);
|
||||
int quark_se_ipm_controller_initialize(struct device *d);
|
||||
|
||||
#define QUARK_SE_IPM_DEFINE(name, ch, dir) \
|
||||
struct quark_se_ipm_config_info quark_se_ipm_config_##name = { \
|
||||
.ipm = QUARK_SE_IPM(ch), \
|
||||
.channel = ch, \
|
||||
.direction = dir \
|
||||
}; \
|
||||
struct quark_se_ipm_driver_data quark_se_ipm_runtime_##name; \
|
||||
DECLARE_DEVICE_INIT_CONFIG(name, _STRINGIFY(name), \
|
||||
quark_se_ipm_initialize, \
|
||||
&quark_se_ipm_config_##name); \
|
||||
SYS_DEFINE_DEVICE(name, &quark_se_ipm_runtime_##name, SECONDARY, \
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT)
|
||||
|
||||
|
||||
#endif /* __INCquark_se_mailboxh */
|
|
@ -21,8 +21,8 @@
|
|||
#include <drivers/ioapic.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_IPI_QUARK_SE)
|
||||
#if defined(CONFIG_IPM_QUARK_SE)
|
||||
#if defined(CONFIG_IOAPIC)
|
||||
ioapic_mkstub quark_se_ipi quark_se_ipi_isr 0
|
||||
ioapic_mkstub quark_se_ipm quark_se_ipm_isr 0
|
||||
#endif
|
||||
#endif
|
|
@ -1,4 +1,4 @@
|
|||
/* ipi_console.c - Console messages to/from another processor */
|
||||
/* ipm_console.c - Console messages to/from another processor */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
|
@ -16,30 +16,30 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _IPI_CONSOLE_H_
|
||||
#define _IPI_CONSOLE_H_
|
||||
#ifndef _IPM_CONSOLE_H_
|
||||
#define _IPM_CONSOLE_H_
|
||||
|
||||
#include <nanokernel.h>
|
||||
#include <device.h>
|
||||
#include <misc/ring_buffer.h>
|
||||
|
||||
#define IPI_CONSOLE_STDOUT (1 << 0)
|
||||
#define IPI_CONSOLE_PRINTK (1 << 1)
|
||||
#define IPM_CONSOLE_STDOUT (1 << 0)
|
||||
#define IPM_CONSOLE_PRINTK (1 << 1)
|
||||
|
||||
/*
|
||||
* Good way to determine these numbers other than trial-and-error?
|
||||
* using printf() in the fiber seems to require a lot more stack space
|
||||
*/
|
||||
#define IPI_CONSOLE_STACK_SIZE 512
|
||||
#define IPI_CONSOLE_PRI 2
|
||||
#define IPM_CONSOLE_STACK_SIZE 512
|
||||
#define IPM_CONSOLE_PRI 2
|
||||
|
||||
struct ipi_console_receiver_config_info {
|
||||
/** Name of the low-level IPI driver to bind to */
|
||||
struct ipm_console_receiver_config_info {
|
||||
/** Name of the low-level IPM driver to bind to */
|
||||
char *bind_to;
|
||||
|
||||
/**
|
||||
* Stack for the receiver's fiber, which prints out messages as
|
||||
* they come in. Should be sized IPI_CONSOLE_STACK_SIZE
|
||||
* they come in. Should be sized IPM_CONSOLE_STACK_SIZE
|
||||
*/
|
||||
char *fiber_stack;
|
||||
|
||||
|
@ -64,39 +64,39 @@ struct ipi_console_receiver_config_info {
|
|||
|
||||
/**
|
||||
* Destination for received console messages, one of
|
||||
* IPI_CONSOLE_STDOUT or IPI_CONSOLE_PRINTK
|
||||
* IPM_CONSOLE_STDOUT or IPM_CONSOLE_PRINTK
|
||||
*/
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
struct ipi_console_receiver_runtime_data {
|
||||
/** Buffer for received bytes from the low-level IPI device */
|
||||
struct ipm_console_receiver_runtime_data {
|
||||
/** Buffer for received bytes from the low-level IPM device */
|
||||
struct ring_buf rb;
|
||||
|
||||
/** Semaphore to wake up the fiber to print out messages */
|
||||
struct nano_sem sem;
|
||||
|
||||
/** pointer to the bound low-level IPI device */
|
||||
struct device *ipi_device;
|
||||
/** pointer to the bound low-level IPM device */
|
||||
struct device *ipm_device;
|
||||
};
|
||||
|
||||
struct ipi_console_sender_config_info {
|
||||
struct ipm_console_sender_config_info {
|
||||
/** Name of the low-level driver to bind to */
|
||||
char *bind_to;
|
||||
|
||||
/**
|
||||
* Source of messages to forward, hooks will be installed.
|
||||
* Can be IPI_CONSOLE_STDOUT, IPI_CONSOLE_PRINTK, or both
|
||||
* Can be IPM_CONSOLE_STDOUT, IPM_CONSOLE_PRINTK, or both
|
||||
*/
|
||||
int flags;
|
||||
};
|
||||
|
||||
#if CONFIG_IPI_CONSOLE_RECEIVER
|
||||
int ipi_console_receiver_init(struct device *d);
|
||||
#if CONFIG_IPM_CONSOLE_RECEIVER
|
||||
int ipm_console_receiver_init(struct device *d);
|
||||
#endif
|
||||
|
||||
#if CONFIG_IPI_CONSOLE_SENDER
|
||||
int ipi_console_sender_init(struct device *d);
|
||||
#if CONFIG_IPM_CONSOLE_SENDER
|
||||
int ipm_console_sender_init(struct device *d);
|
||||
#endif
|
||||
|
||||
#endif /* _IPI_CONSOLE_H_ */
|
||||
#endif /* _IPM_CONSOLE_H_ */
|
|
@ -1,4 +1,4 @@
|
|||
/* ipi.h - Generic low-level inter-processor interrupt communication API */
|
||||
/* ipm.h - Generic low-level inter-processor mailbox communication API */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
|
@ -16,12 +16,12 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __INCipih
|
||||
#define __INCipih
|
||||
#ifndef __INCipmh
|
||||
#define __INCipmh
|
||||
|
||||
/**
|
||||
* @brief IPI Interface
|
||||
* @defgroup ipi_interface IPI Interface
|
||||
* @brief IPM Interface
|
||||
* @defgroup ipm_interface IPM Interface
|
||||
* @ingroup io_interfaces
|
||||
* @{
|
||||
*/
|
||||
|
@ -30,52 +30,52 @@
|
|||
#include <device.h>
|
||||
|
||||
/**
|
||||
* Callback API for incoming IPI messages
|
||||
* Callback API for incoming IPM messages
|
||||
*
|
||||
* These callbacks are executed in interrupt context, and only interrupt-
|
||||
* safe APIS may be used. Registration of callbacks is done via
|
||||
* ipi_register_callback()
|
||||
* ipm_register_callback()
|
||||
*
|
||||
* @param context Arbitrary context pointer provided at registration time
|
||||
* @param id Message type identifier
|
||||
* @param data Message data pointer. The correct amount of data to read out
|
||||
* needs to be inferred by the message id/upper level protocol
|
||||
*/
|
||||
typedef void (*ipi_callback_t)(void *context, uint32_t id, volatile void *data);
|
||||
typedef void (*ipm_callback_t)(void *context, uint32_t id, volatile void *data);
|
||||
|
||||
typedef int (*ipi_send_t)(struct device *ipidev, int wait, uint32_t id,
|
||||
typedef int (*ipm_send_t)(struct device *ipmdev, int wait, uint32_t id,
|
||||
const void *data, int size);
|
||||
typedef int (*ipi_max_data_size_get_t)(struct device *ipidev);
|
||||
typedef uint32_t (*ipi_max_id_val_get_t)(struct device *ipidev);
|
||||
typedef void (*ipi_register_callback_t)(struct device *port, ipi_callback_t cb,
|
||||
typedef int (*ipm_max_data_size_get_t)(struct device *ipmdev);
|
||||
typedef uint32_t (*ipm_max_id_val_get_t)(struct device *ipmdev);
|
||||
typedef void (*ipm_register_callback_t)(struct device *port, ipm_callback_t cb,
|
||||
void *cb_context);
|
||||
typedef int (*ipi_set_enabled_t)(struct device *ipidev, int enable);
|
||||
typedef int (*ipm_set_enabled_t)(struct device *ipmdev, int enable);
|
||||
|
||||
struct ipi_driver_api {
|
||||
ipi_send_t send;
|
||||
ipi_register_callback_t register_callback;
|
||||
ipi_max_data_size_get_t max_data_size_get;
|
||||
ipi_max_id_val_get_t max_id_val_get;
|
||||
ipi_set_enabled_t set_enabled;
|
||||
struct ipm_driver_api {
|
||||
ipm_send_t send;
|
||||
ipm_register_callback_t register_callback;
|
||||
ipm_max_data_size_get_t max_data_size_get;
|
||||
ipm_max_id_val_get_t max_id_val_get;
|
||||
ipm_set_enabled_t set_enabled;
|
||||
};
|
||||
|
||||
/**
|
||||
* Try to send a message over the IPI device
|
||||
* Try to send a message over the IPM device
|
||||
*
|
||||
* @param ipidev Driver instance
|
||||
* @param ipmdev Driver instance
|
||||
* @param wait If nonzero, busy-wait for remote to consume the message. The
|
||||
* message is considered consumed once the remote interrupt handler
|
||||
* finishes. If there is deferred processing on the remote side,
|
||||
* or you would like to queue outgoing messages and wait on an
|
||||
* event/semaphore, you can implement that in a high-level driver
|
||||
* @param id Message identifier. Values are constrained by
|
||||
* ipi_max_data_size_get() since many platforms only allow for a
|
||||
* ipm_max_data_size_get() since many platforms only allow for a
|
||||
* subset of bits in a 32-bit register to store the ID.
|
||||
* @param data Pointer to data to send in the message
|
||||
* @param size size of the data pointed to
|
||||
*
|
||||
* There are constraints on how much data can be sent or the maximum value
|
||||
* of id, use the ipi_max_data_size_get() and ipi_max_id_val_get() functions
|
||||
* of id, use the ipm_max_data_size_get() and ipm_max_id_val_get() functions
|
||||
* to determine these.
|
||||
*
|
||||
* The size parameter is only used on the sending side to know how much data
|
||||
|
@ -86,89 +86,89 @@ struct ipi_driver_api {
|
|||
* @return -EBUSY if the remote hasn't yet read the last data sent
|
||||
* -EMSGSIZE If the supplied data size is unsupported by the driver
|
||||
* -EINVAL Bad parameter, such as a too-large id value, or
|
||||
* the device isn't an outbound IPI channel
|
||||
* the device isn't an outbound IPM channel
|
||||
* 0 Success
|
||||
*/
|
||||
static inline int ipi_send(struct device *ipidev, int wait, uint32_t id,
|
||||
static inline int ipm_send(struct device *ipmdev, int wait, uint32_t id,
|
||||
void *data, int size)
|
||||
{
|
||||
struct ipi_driver_api *api;
|
||||
struct ipm_driver_api *api;
|
||||
|
||||
api = (struct ipi_driver_api *) ipidev->driver_api;
|
||||
return api->send(ipidev, wait, id, data, size);
|
||||
api = (struct ipm_driver_api *) ipmdev->driver_api;
|
||||
return api->send(ipmdev, wait, id, data, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback function for incoming messages
|
||||
*
|
||||
* @param ipidev Driver instance
|
||||
* @param ipmdev Driver instance
|
||||
* @param cb Callback function to execute on incoming message interrupts
|
||||
* @param context Application-specific context pointer which will be passed
|
||||
* to the callback function when executed.
|
||||
*/
|
||||
static inline void ipi_register_callback(struct device *ipidev,
|
||||
ipi_callback_t cb, void *context)
|
||||
static inline void ipm_register_callback(struct device *ipmdev,
|
||||
ipm_callback_t cb, void *context)
|
||||
{
|
||||
struct ipi_driver_api *api;
|
||||
struct ipm_driver_api *api;
|
||||
|
||||
api = (struct ipi_driver_api *) ipidev->driver_api;
|
||||
api->register_callback(ipidev, cb, context);
|
||||
api = (struct ipm_driver_api *) ipmdev->driver_api;
|
||||
api->register_callback(ipmdev, cb, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maxmimum number of bytes that can be sent in an outbound message
|
||||
*
|
||||
* IPI implementations vary in how much data can be sent in a single message
|
||||
* IPM implementations vary in how much data can be sent in a single message
|
||||
* since the data payload is typically stored in registers.
|
||||
*
|
||||
* @param ipidev Driver instance pointer
|
||||
* @param ipmdev Driver instance pointer
|
||||
*
|
||||
* @return Max size of a message in bytes
|
||||
*/
|
||||
static inline int ipi_max_data_size_get(struct device *ipidev)
|
||||
static inline int ipm_max_data_size_get(struct device *ipmdev)
|
||||
{
|
||||
struct ipi_driver_api *api;
|
||||
struct ipm_driver_api *api;
|
||||
|
||||
api = (struct ipi_driver_api *) ipidev->driver_api;
|
||||
return api->max_data_size_get(ipidev);
|
||||
api = (struct ipm_driver_api *) ipmdev->driver_api;
|
||||
return api->max_data_size_get(ipmdev);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the maximum id value that can be sent in an outbound message
|
||||
*
|
||||
* Many IPI implementations store the id in a register which may have some bits
|
||||
* Many IPM implementations store the id in a register which may have some bits
|
||||
* reserved for other use
|
||||
*
|
||||
* @param ipidev Driver instance pointer
|
||||
* @param ipmdev Driver instance pointer
|
||||
*
|
||||
* @return Maximum value of a message id
|
||||
*/
|
||||
static inline uint32_t ipi_max_id_val_get(struct device *ipidev)
|
||||
static inline uint32_t ipm_max_id_val_get(struct device *ipmdev)
|
||||
{
|
||||
struct ipi_driver_api *api;
|
||||
struct ipm_driver_api *api;
|
||||
|
||||
api = (struct ipi_driver_api *) ipidev->driver_api;
|
||||
return api->max_id_val_get(ipidev);
|
||||
api = (struct ipm_driver_api *) ipmdev->driver_api;
|
||||
return api->max_id_val_get(ipmdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* For inbound channels, enable interrupts/callbacks
|
||||
*
|
||||
* @param ipidev Driver instance pointer
|
||||
* @param ipmdev Driver instance pointer
|
||||
* @param enable 0=disable nonzero=enable
|
||||
*
|
||||
* @return 0 on success, -EINVAL if this isn't an inbound channel
|
||||
*/
|
||||
static inline int ipi_set_enabled(struct device *ipidev, int enable)
|
||||
static inline int ipm_set_enabled(struct device *ipmdev, int enable)
|
||||
{
|
||||
struct ipi_driver_api *api;
|
||||
struct ipm_driver_api *api;
|
||||
|
||||
api = (struct ipi_driver_api *) ipidev->driver_api;
|
||||
return api->set_enabled(ipidev, enable);
|
||||
api = (struct ipm_driver_api *) ipmdev->driver_api;
|
||||
return api->set_enabled(ipmdev, enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* __INCipih */
|
||||
#endif /* __INCipmh */
|
|
@ -11,5 +11,5 @@ CONFIG_NUM_TIMER_PACKETS=4
|
|||
CONFIG_MICROKERNEL_SERVER_STACK_SIZE=128
|
||||
CONFIG_CONSOLE=n
|
||||
CONFIG_SERIAL=n
|
||||
CONFIG_IPI=n
|
||||
CONFIG_IPM=n
|
||||
CONFIG_ERRNO=n
|
||||
|
|
|
@ -6,5 +6,5 @@ CONFIG_HPET_TIMER_IRQ_PRIORITY=2
|
|||
CONFIG_IDT_NUM_VECTORS=33
|
||||
CONFIG_CONSOLE=n
|
||||
CONFIG_SERIAL=n
|
||||
CONFIG_IPI=n
|
||||
CONFIG_IPM=n
|
||||
CONFIG_ERRNO=n
|
||||
|
|
|
@ -1,110 +0,0 @@
|
|||
/* ipi_dummy.c - Fake IPI driver */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <ipi.h>
|
||||
#include <drivers/console/ipi_console.h>
|
||||
#include <device.h>
|
||||
#include <init.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <tc_util.h>
|
||||
#include "ipi_dummy.h"
|
||||
|
||||
#define PRINTK_OUT 1
|
||||
|
||||
#if PRINTK_OUT
|
||||
#define SOURCE IPI_CONSOLE_STDOUT
|
||||
#define DEST IPI_CONSOLE_PRINTK
|
||||
#else
|
||||
#define SOURCE IPI_CONSOLE_PRINTK
|
||||
#define DEST IPI_CONSOLE_STDOUT
|
||||
#endif
|
||||
|
||||
#define INIT_PRIO_IPI_SEND 50
|
||||
|
||||
/* Set up the dummy IPI driver */
|
||||
struct ipi_dummy_driver_data ipi_dummy0_driver_data;
|
||||
DECLARE_DEVICE_INIT_CONFIG(ipi_dummy0, "ipi_dummy0", ipi_dummy_init, NULL);
|
||||
SYS_DEFINE_DEVICE(ipi_dummy0, &ipi_dummy0_driver_data, SECONDARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
|
||||
/* Sending side of the console IPI driver, will forward anything sent
|
||||
* to printf() since we selected IPI_CONSOLE_STDOUT */
|
||||
struct ipi_console_sender_config_info sender_config = {
|
||||
.bind_to = "ipi_dummy0",
|
||||
.flags = SOURCE
|
||||
};
|
||||
DECLARE_DEVICE_INIT_CONFIG(ipi_console_send0, "ipi_send0",
|
||||
ipi_console_sender_init, &sender_config);
|
||||
SYS_DEFINE_DEVICE(ipi_console_send0, NULL, NANOKERNEL,
|
||||
INIT_PRIO_IPI_SEND);
|
||||
|
||||
/* Receiving side of the console IPI driver. These numbers are
|
||||
* more or less arbitrary */
|
||||
#define LINE_BUF_SIZE 80
|
||||
#define RING_BUF_SIZE32 8
|
||||
|
||||
static uint32_t ring_buf_data[RING_BUF_SIZE32];
|
||||
static char __stack fiber_stack[IPI_CONSOLE_STACK_SIZE];
|
||||
static char line_buf[LINE_BUF_SIZE];
|
||||
|
||||
/* Dump incoming messages to printk() */
|
||||
struct ipi_console_receiver_config_info receiver_config = {
|
||||
.bind_to = "ipi_dummy0",
|
||||
.fiber_stack = fiber_stack,
|
||||
.ring_buf_data = ring_buf_data,
|
||||
.rb_size32 = RING_BUF_SIZE32,
|
||||
.line_buf = line_buf,
|
||||
.lb_size = LINE_BUF_SIZE,
|
||||
.flags = DEST
|
||||
};
|
||||
struct ipi_console_receiver_runtime_data receiver_data;
|
||||
DECLARE_DEVICE_INIT_CONFIG(ipi_console_recv0, "ipi_recv0",
|
||||
ipi_console_receiver_init, &receiver_config);
|
||||
SYS_DEFINE_DEVICE(ipi_console_recv0, &receiver_data, NANOKERNEL,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
|
||||
static const char thestr[] = "everything is awesome\n";
|
||||
|
||||
void main(void)
|
||||
{
|
||||
int rv, i;
|
||||
struct device *ipi;
|
||||
|
||||
TC_START("Test IPI");
|
||||
ipi = device_get_binding("ipi_dummy0");
|
||||
|
||||
/* Try sending a raw string to the IPI device to show that the
|
||||
* receiver works */
|
||||
for (i = 0; i < strlen(thestr); i++) {
|
||||
ipi_send(ipi, 1, thestr[i], NULL, 0);
|
||||
}
|
||||
|
||||
/* Now do this through printf() to exercise the sender */
|
||||
printf("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n");
|
||||
|
||||
/* XXX how to tell if something was actually printed out for
|
||||
* automation purposes? */
|
||||
|
||||
rv = TC_PASS;
|
||||
TC_END_RESULT(rv);
|
||||
TC_END_REPORT(rv);
|
||||
}
|
||||
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
CONFIG_NUM_IRQS=2
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_STDOUT_CONSOLE=y
|
||||
CONFIG_IPI_CONSOLE_RECEIVER=y
|
||||
CONFIG_IPI_CONSOLE_SENDER=y
|
||||
CONFIG_IPM_CONSOLE_RECEIVER=y
|
||||
CONFIG_IPM_CONSOLE_SENDER=y
|
||||
CONFIG_IRQ_OFFLOAD=y
|
||||
CONFIG_DEBUG=y
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
CONFIG_CONSOLE=y
|
||||
CONFIG_STDOUT_CONSOLE=y
|
||||
CONFIG_IPI_CONSOLE_RECEIVER=y
|
||||
CONFIG_IPI_CONSOLE_SENDER=y
|
||||
CONFIG_IPM_CONSOLE_RECEIVER=y
|
||||
CONFIG_IPM_CONSOLE_SENDER=y
|
||||
CONFIG_IRQ_OFFLOAD=y
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
ccflags-y += -I${srctree}/samples/include
|
||||
|
||||
obj-y = ipi_dummy.o test_ipi.o
|
||||
obj-y = ipm_dummy.o test_ipm.o
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
/* ipi_dummy.c - Fake IPI driver for testing upper-level drivers */
|
||||
/* ipm_dummy.c - Fake IPM driver for testing upper-level drivers */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
|
@ -17,25 +17,28 @@
|
|||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <ipi.h>
|
||||
#include <ipm.h>
|
||||
#include <errno.h>
|
||||
#include <device.h>
|
||||
#include <init.h>
|
||||
#include <misc/printk.h>
|
||||
#include <irq_offload.h>
|
||||
|
||||
#include "ipi_dummy.h"
|
||||
#include "ipm_dummy.h"
|
||||
|
||||
|
||||
|
||||
/* Implemented as a software interrupt so that callbacks are executed
|
||||
* in the expected context */
|
||||
static void ipi_dummy_isr(void *data)
|
||||
* in the expected context
|
||||
*/
|
||||
static void ipm_dummy_isr(void *data)
|
||||
{
|
||||
struct device *d = (struct device *)data;
|
||||
struct ipi_dummy_driver_data *driver_data = d->driver_data;
|
||||
struct ipm_dummy_driver_data *driver_data = d->driver_data;
|
||||
|
||||
/* In a real driver the interrupt simply wouldn't fire, we fake
|
||||
* that here */
|
||||
* that here
|
||||
*/
|
||||
if (!driver_data->regs.enabled || !driver_data->regs.busy)
|
||||
return;
|
||||
|
||||
|
@ -47,18 +50,18 @@ static void ipi_dummy_isr(void *data)
|
|||
}
|
||||
|
||||
|
||||
/* IPI API functions for the dummy driver */
|
||||
/* IPM API functions for the dummy driver */
|
||||
|
||||
static int ipi_dummy_send(struct device *d, int wait, uint32_t id,
|
||||
static int ipm_dummy_send(struct device *d, int wait, uint32_t id,
|
||||
const void *data, int size)
|
||||
{
|
||||
struct ipi_dummy_driver_data *driver_data;
|
||||
struct ipm_dummy_driver_data *driver_data;
|
||||
volatile uint8_t *datareg;
|
||||
const uint8_t *data8;
|
||||
int i;
|
||||
|
||||
driver_data = d->driver_data;
|
||||
if (size > ipi_max_data_size_get(d)) {
|
||||
if (size > ipm_max_data_size_get(d)) {
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
|
@ -75,64 +78,66 @@ static int ipi_dummy_send(struct device *d, int wait, uint32_t id,
|
|||
driver_data->regs.id = id;
|
||||
driver_data->regs.busy = 1;
|
||||
|
||||
irq_offload(ipi_dummy_isr, d);
|
||||
irq_offload(ipm_dummy_isr, d);
|
||||
|
||||
if (wait) {
|
||||
while(driver_data->regs.busy) {
|
||||
while (driver_data->regs.busy) {
|
||||
/* busy-wait */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ipi_dummy_register_callback(struct device *d, ipi_callback_t cb,
|
||||
static void ipm_dummy_register_callback(struct device *d, ipm_callback_t cb,
|
||||
void *cb_context)
|
||||
{
|
||||
struct ipi_dummy_driver_data *driver_data;
|
||||
struct ipm_dummy_driver_data *driver_data;
|
||||
|
||||
driver_data = d->driver_data;
|
||||
driver_data->cb = cb;
|
||||
driver_data->cb_context = cb_context;
|
||||
}
|
||||
|
||||
static int ipi_dummy_set_enabled(struct device *d, int enable)
|
||||
static int ipm_dummy_set_enabled(struct device *d, int enable)
|
||||
{
|
||||
struct ipi_dummy_driver_data *driver_data = d->driver_data;
|
||||
struct ipm_dummy_driver_data *driver_data = d->driver_data;
|
||||
|
||||
driver_data->regs.enabled = enable;
|
||||
if (enable) {
|
||||
/* In case there are pending messages */
|
||||
irq_offload(ipi_dummy_isr, d);
|
||||
irq_offload(ipm_dummy_isr, d);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t ipi_dummy_max_id_val_get(struct device *d)
|
||||
static uint32_t ipm_dummy_max_id_val_get(struct device *d)
|
||||
{
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
static int ipi_dummy_max_data_size_get(struct device *d)
|
||||
static int ipm_dummy_max_data_size_get(struct device *d)
|
||||
{
|
||||
return DUMMY_IPI_DATA_WORDS * sizeof(uint32_t);
|
||||
return DUMMY_IPM_DATA_WORDS * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
struct ipi_driver_api ipi_dummy_api = {
|
||||
.send = ipi_dummy_send,
|
||||
.register_callback = ipi_dummy_register_callback,
|
||||
.max_data_size_get = ipi_dummy_max_data_size_get,
|
||||
.max_id_val_get = ipi_dummy_max_id_val_get,
|
||||
.set_enabled = ipi_dummy_set_enabled
|
||||
struct ipm_driver_api ipm_dummy_api = {
|
||||
.send = ipm_dummy_send,
|
||||
.register_callback = ipm_dummy_register_callback,
|
||||
.max_data_size_get = ipm_dummy_max_data_size_get,
|
||||
.max_id_val_get = ipm_dummy_max_id_val_get,
|
||||
.set_enabled = ipm_dummy_set_enabled
|
||||
};
|
||||
|
||||
/* Dummy IPI driver initialization, will be bound at runtime
|
||||
* to high-level drivers under test */
|
||||
/* Dummy IPM driver initialization, will be bound at runtime
|
||||
* to high-level drivers under test
|
||||
*/
|
||||
|
||||
int ipi_dummy_init(struct device *d)
|
||||
int ipm_dummy_init(struct device *d)
|
||||
{
|
||||
struct ipi_dummy_driver_data *driver_data;
|
||||
struct ipm_dummy_driver_data *driver_data;
|
||||
|
||||
driver_data = d->driver_data;
|
||||
d->driver_api = &ipi_dummy_api;
|
||||
d->driver_api = &ipm_dummy_api;
|
||||
|
||||
return DEV_OK;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* ipi_dummy.c - Fake IPI driver */
|
||||
/* ipm_dummy.c - Fake IPM driver */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
|
@ -16,28 +16,27 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _IPI_DUMMY_H_
|
||||
#ifndef _IPM_DUMMY_H_
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <device.h>
|
||||
#include <ipi.h>
|
||||
#include <ipm.h>
|
||||
|
||||
/* Arbitrary */
|
||||
#define DUMMY_IPI_DATA_WORDS 4
|
||||
#define DUMMY_IPM_DATA_WORDS 4
|
||||
|
||||
struct ipi_dummy_regs {
|
||||
struct ipm_dummy_regs {
|
||||
uint32_t id;
|
||||
uint32_t data[DUMMY_IPI_DATA_WORDS];
|
||||
uint32_t data[DUMMY_IPM_DATA_WORDS];
|
||||
uint8_t busy;
|
||||
uint8_t enabled;
|
||||
};
|
||||
|
||||
struct ipi_dummy_driver_data {
|
||||
ipi_callback_t cb;
|
||||
struct ipm_dummy_driver_data {
|
||||
ipm_callback_t cb;
|
||||
void *cb_context;
|
||||
volatile struct ipi_dummy_regs regs;
|
||||
volatile struct ipm_dummy_regs regs;
|
||||
};
|
||||
|
||||
int ipi_dummy_init(struct device *d);
|
||||
|
||||
int ipm_dummy_init(struct device *d);
|
||||
#endif
|
122
samples/nanokernel/test/test_ipm/src/test_ipm.c
Normal file
122
samples/nanokernel/test/test_ipm/src/test_ipm.c
Normal file
|
@ -0,0 +1,122 @@
|
|||
/* ipm_dummy.c - Fake IPM driver */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <ipm.h>
|
||||
#include <drivers/console/ipm_console.h>
|
||||
#include <device.h>
|
||||
#include <init.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <tc_util.h>
|
||||
#include "ipm_dummy.h"
|
||||
|
||||
#define PRINTK_OUT 1
|
||||
|
||||
#if PRINTK_OUT
|
||||
#define SOURCE IPM_CONSOLE_STDOUT
|
||||
#define DEST IPM_CONSOLE_PRINTK
|
||||
#else
|
||||
#define SOURCE IPM_CONSOLE_PRINTK
|
||||
#define DEST IPM_CONSOLE_STDOUT
|
||||
#endif
|
||||
|
||||
#define INIT_PRIO_IPM_SEND 50
|
||||
|
||||
/* Set up the dummy IPM driver */
|
||||
struct ipm_dummy_driver_data ipm_dummy0_driver_data;
|
||||
DECLARE_DEVICE_INIT_CONFIG(ipm_dummy0, "ipm_dummy0", ipm_dummy_init, NULL);
|
||||
SYS_DEFINE_DEVICE(ipm_dummy0, &ipm_dummy0_driver_data, SECONDARY,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
|
||||
/* Sending side of the console IPM driver, will forward anything sent
|
||||
* to printf() since we selected IPM_CONSOLE_STDOUT
|
||||
*/
|
||||
struct ipm_console_sender_config_info sender_config = {
|
||||
.bind_to = "ipm_dummy0",
|
||||
.flags = SOURCE
|
||||
};
|
||||
DECLARE_DEVICE_INIT_CONFIG(ipm_console_send0, "ipm_send0",
|
||||
ipm_console_sender_init, &sender_config);
|
||||
SYS_DEFINE_DEVICE(ipm_console_send0, NULL, NANOKERNEL,
|
||||
INIT_PRIO_IPM_SEND);
|
||||
|
||||
/* Receiving side of the console IPM driver. These numbers are
|
||||
* more or less arbitrary
|
||||
*/
|
||||
#define LINE_BUF_SIZE 80
|
||||
#define RING_BUF_SIZE32 8
|
||||
|
||||
static uint32_t ring_buf_data[RING_BUF_SIZE32];
|
||||
static char __stack fiber_stack[IPM_CONSOLE_STACK_SIZE];
|
||||
static char line_buf[LINE_BUF_SIZE];
|
||||
|
||||
/* Dump incoming messages to printk() */
|
||||
struct ipm_console_receiver_config_info receiver_config = {
|
||||
.bind_to = "ipm_dummy0",
|
||||
.fiber_stack = fiber_stack,
|
||||
.ring_buf_data = ring_buf_data,
|
||||
.rb_size32 = RING_BUF_SIZE32,
|
||||
.line_buf = line_buf,
|
||||
.lb_size = LINE_BUF_SIZE,
|
||||
.flags = DEST
|
||||
};
|
||||
|
||||
struct ipm_console_receiver_runtime_data receiver_data;
|
||||
DECLARE_DEVICE_INIT_CONFIG(ipm_console_recv0, "ipm_recv0",
|
||||
ipm_console_receiver_init, &receiver_config);
|
||||
SYS_DEFINE_DEVICE(ipm_console_recv0, &receiver_data, NANOKERNEL,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
|
||||
static const char thestr[] = "everything is awesome\n";
|
||||
|
||||
void main(void)
|
||||
{
|
||||
int rv, i;
|
||||
struct device *ipm;
|
||||
|
||||
TC_START("Test IPM");
|
||||
ipm = device_get_binding("ipm_dummy0");
|
||||
|
||||
/* Try sending a raw string to the IPM device to show that the
|
||||
* receiver works
|
||||
*/
|
||||
for (i = 0; i < strlen(thestr); i++) {
|
||||
ipm_send(ipm, 1, thestr[i], NULL, 0);
|
||||
}
|
||||
|
||||
/* Now do this through printf() to exercise the sender */
|
||||
printf("Lorem ipsum dolor sit amet, consectetur adipiscing elit, "
|
||||
"sed do eiusmod tempor incididunt ut labore et dolore magna "
|
||||
"aliqua. Ut enim ad minim veniam, quis nostrud exercitation "
|
||||
"ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis "
|
||||
"aute irure dolor in reprehenderit in voluptate velit esse "
|
||||
"cillum dolore eu fugiat nulla pariatur. Excepteur sint "
|
||||
"occaecat cupidatat non proident, sunt in culpa qui officia "
|
||||
"deserunt mollit anim id est laborum.\n");
|
||||
|
||||
/* XXX how to tell if something was actually printed out for
|
||||
* automation purposes?
|
||||
*/
|
||||
|
||||
rv = TC_PASS;
|
||||
TC_END_RESULT(rv);
|
||||
TC_END_REPORT(rv);
|
||||
}
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue