From 8d69832bfda87062934d66bc334088a1fe4ada20 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Mon, 9 Dec 2019 14:33:37 +0200 Subject: [PATCH] console: ipm_console: Add console over IPM Add console over Inter Processor Mailboxes (IPM). This is useful for AMP processors like ADSP found on up_squared board. Signed-off-by: Andrei Emeltchenko --- drivers/console/CMakeLists.txt | 1 + drivers/console/Kconfig | 30 +++++++++++ drivers/console/ipm_console.c | 91 ++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 drivers/console/ipm_console.c diff --git a/drivers/console/CMakeLists.txt b/drivers/console/CMakeLists.txt index 46b6eb53fd..a7097f6607 100644 --- a/drivers/console/CMakeLists.txt +++ b/drivers/console/CMakeLists.txt @@ -5,6 +5,7 @@ zephyr_sources_ifdef(CONFIG_RAM_CONSOLE ram_console.c) zephyr_sources_ifdef(CONFIG_RTT_CONSOLE rtt_console.c) zephyr_sources_ifdef(CONFIG_IPM_CONSOLE_RECEIVER ipm_console_receiver.c) zephyr_sources_ifdef(CONFIG_IPM_CONSOLE_SENDER ipm_console_sender.c) +zephyr_sources_ifdef(CONFIG_IPM_CONSOLE ipm_console.c) zephyr_sources_ifdef(CONFIG_UART_MCUMGR uart_mcumgr.c) zephyr_sources_ifdef(CONFIG_UART_PIPE uart_pipe.c) zephyr_sources_ifdef(CONFIG_XTENSA_SIM_CONSOLE xtensa_sim_console.c) diff --git a/drivers/console/Kconfig b/drivers/console/Kconfig index 55b5c80a09..8896e3c326 100644 --- a/drivers/console/Kconfig +++ b/drivers/console/Kconfig @@ -168,6 +168,36 @@ config IPM_CONSOLE_STACK_SIZE thread to print out incoming messages from the remote CPU. Specify the stack size for these threads here. +config IPM_CONSOLE + bool "Inter-processor Mailbox console" + depends on IPM + select CONSOLE_HAS_DRIVER + help + Enable console over Inter-processor Mailbox. + +config IPM_CONSOLE_ON_DEV_NAME + string "IPM device name used by console" + default "IPM_0" + depends on IPM_CONSOLE + help + IPM device name used by IPM console driver. + +config IPM_CONSOLE_LINE_BUF_LEN + int "IPM console line buffer length" + default 128 + depends on IPM_CONSOLE + help + IPM console line buffer length specify amount of the buffer + where characters are stored before sending the whole line. + +config IPM_CONSOLE_IMMEDIATE + bool "Immediate logging over IPM" + default y + depends on IPM_CONSOLE + help + When enabled console output is processed in the context of the call. Output + is blocked until read by the Host. + config UART_PIPE bool "Enable pipe UART driver" select UART_INTERRUPT_DRIVEN diff --git a/drivers/console/ipm_console.c b/drivers/console/ipm_console.c new file mode 100644 index 0000000000..852daff619 --- /dev/null +++ b/drivers/console/ipm_console.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(ipm_console, CONFIG_IPM_LOG_LEVEL); + +struct device *ipm_dev; + +static int console_out(int c) +{ + static char buf[CONFIG_IPM_CONSOLE_LINE_BUF_LEN]; + static size_t len; + int ret; + + if (c != '\n' && len < sizeof(buf)) { + buf[len++] = c; + return c; + } + + ret = ipm_send(ipm_dev, 1, len, buf, len); + if (ret) { + LOG_ERR("Error sending character %c over IPM, ret %d", c, ret); + } + + memset(buf, 0, sizeof(buf)); + len = 0; + + /* After buffer is full start a new one */ + if (c != '\n') { + buf[len++] = c; + } + + return c; +} + +#if defined(CONFIG_STDOUT_CONSOLE) +extern void __stdout_hook_install(int (*hook)(int)); +#else +#define __stdout_hook_install(x) \ + do { /* nothing */ \ + } while ((0)) +#endif + +#if defined(CONFIG_PRINTK) +extern void __printk_hook_install(int (*fn)(int)); +#else +#define __printk_hook_install(x) \ + do { /* nothing */ \ + } while ((0)) +#endif + +/* Install printk/stdout hooks */ +static void ipm_console_hook_install(void) +{ + __stdout_hook_install(console_out); + __printk_hook_install(console_out); +} + +static int ipm_console_init(struct device *dev) +{ + ARG_UNUSED(dev); + + LOG_DBG("IPM console initialization"); + + ipm_dev = device_get_binding(CONFIG_IPM_CONSOLE_ON_DEV_NAME); + if (!ipm_dev) { + LOG_ERR("Cannot get %s", CONFIG_IPM_CONSOLE_ON_DEV_NAME); + return -ENODEV; + } + + if (ipm_max_id_val_get(ipm_dev) < CONFIG_IPM_CONSOLE_LINE_BUF_LEN) { + LOG_ERR("IPM driver does not support buffer length %d", + CONFIG_IPM_CONSOLE_LINE_BUF_LEN); + return -ENOTSUP; + } + + ipm_console_hook_install(); + + return 0; +} + +/* Need to be initialized after IPM */ +SYS_INIT(ipm_console_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);