drivers: misc: add NXP S32 eMIOS driver

This PR adds a misc driver for NXP S32 eMIOS peripheral.
eMIOS provides multiple unified channels (UCs), there are
several channels can be used as reference timebase
(master bus) for other channels. At this time, the
driver does initialize global configuration for eMIOS

Signed-off-by: Dat Nguyen Duy <dat.nguyenduy@nxp.com>
This commit is contained in:
Dat Nguyen Duy 2023-08-21 15:31:34 +07:00 committed by Carles Cufí
commit e5e2f2fad8
7 changed files with 376 additions and 0 deletions

View file

@ -4,3 +4,4 @@ add_subdirectory_ifdef(CONFIG_ARM_ETHOS_U ethos_u)
add_subdirectory_ifdef(CONFIG_FT800 ft8xx)
add_subdirectory_ifdef(CONFIG_GROVE_LCD_RGB grove_lcd_rgb)
add_subdirectory_ifdef(CONFIG_PIO_RPI_PICO pio_rpi_pico)
add_subdirectory_ifdef(CONFIG_NXP_S32_EMIOS nxp_s32_emios)

View file

@ -8,5 +8,6 @@ menu "Miscellaneous Drivers"
source "drivers/misc/ft8xx/Kconfig"
source "drivers/misc/grove_lcd_rgb/Kconfig"
source "drivers/misc/pio_rpi_pico/Kconfig"
source "drivers/misc/nxp_s32_emios/Kconfig"
endmenu

View file

@ -0,0 +1,8 @@
# Copyright 2023 NXP
# SPDX-License-Identifier: Apache-2.0
zephyr_library()
zephyr_library_sources_ifdef(CONFIG_NXP_S32_EMIOS
nxp_s32_emios.c
)

View file

@ -0,0 +1,22 @@
# Copyright 2023 NXP
# SPDX-License-Identifier: Apache-2.0
config NXP_S32_EMIOS
bool "NXP S32 eMIOS drivers"
depends on DT_HAS_NXP_S32_EMIOS_ENABLED
help
Enable drivers for NXP S32 EMIOS
if NXP_S32_EMIOS
module = NXP_S32_EMIOS
module-str = NXP S32 eMIOS
source "subsys/logging/Kconfig.template.log_config"
config NXP_S32_EMIOS_INIT_PRIORITY
int "NXP S32 eMIOS initialization priority"
default KERNEL_INIT_PRIORITY_DEVICE
help
System initialization priority for NXP S32 eMIOS drivers.
endif

View file

@ -0,0 +1,105 @@
/*
* Copyright 2023 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#define LOG_MODULE_NAME nxp_s32_emios
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_NXP_S32_EMIOS_LOG_LEVEL);
#include <Emios_Mcl_Ip.h>
#define DT_DRV_COMPAT nxp_s32_emios
struct nxp_s32_emios_config {
uint8_t instance;
Emios_Mcl_Ip_ConfigType *mcl_info;
};
static int nxp_s32_emios_init(const struct device *dev)
{
const struct nxp_s32_emios_config *config = dev->config;
if (Emios_Mcl_Ip_Init(config->instance, config->mcl_info)) {
LOG_ERR("Could not initialize eMIOS");
return -EINVAL;
}
return 0;
}
#define MAX_MASTER_BUS_PERIOD 65535U
#define MIN_MASTER_BUS_PERIOD 2U
#define MAX_GLOB_PRESCALER 256U
#define MIN_GLOB_PRESCALER 1U
#define NXP_S32_EMIOS_MASTER_BUS_MODE(mode) DT_CAT(EMIOS_IP_, mode)
#define NXP_S32_EMIOS_INSTANCE_CHECK(idx, n) \
((DT_INST_REG_ADDR(n) == IP_EMIOS_##idx##_BASE) ? idx : 0)
#define NXP_S32_EMIOS_GET_INSTANCE(n) \
LISTIFY(__DEBRACKET eMIOS_INSTANCE_COUNT, NXP_S32_EMIOS_INSTANCE_CHECK, (|), n)
#define NXP_S32_EMIOS_GENERATE_GLOBAL_CONFIG(n) \
BUILD_ASSERT(IN_RANGE(DT_INST_PROP(n, clock_divider), \
MIN_GLOB_PRESCALER, MAX_GLOB_PRESCALER), \
"Divider for eMIOS global prescaler is out of range"); \
const Emios_Ip_GlobalConfigType nxp_s32_emios_##n##_global_config = { \
.allowDebugMode = true, \
.clkDivVal = DT_INST_PROP(n, clock_divider) - 1U, \
.enableGlobalTimeBase = true \
};
#define NXP_S32_EMIOS_MASTER_BUS_VERIFY(node_id) \
BUILD_ASSERT(IN_RANGE(DT_PROP(node_id, period), \
MIN_MASTER_BUS_PERIOD, MAX_MASTER_BUS_PERIOD), \
"Node "DT_NODE_PATH(node_id)": period is out of range");
#define NXP_S32_EMIOS_MASTER_BUS_CONFIG(node_id) \
{ \
.hwChannel = DT_PROP(node_id, channel), \
.defaultPeriod = DT_PROP(node_id, period), \
.masterBusPrescaler = DT_PROP(node_id, prescaler) - 1, \
.allowDebugMode = DT_PROP(node_id, freeze), \
.masterMode = NXP_S32_EMIOS_MASTER_BUS_MODE(DT_STRING_TOKEN(node_id, mode)), \
.masterBusAltPrescaler = 0, \
},
#define NXP_S32_EMIOS_GENERATE_MASTER_BUS_CONFIG(n) \
DT_FOREACH_CHILD_STATUS_OKAY(DT_INST_CHILD(n, master_bus), \
NXP_S32_EMIOS_MASTER_BUS_VERIFY) \
const Emios_Ip_MasterBusConfigType nxp_s32_emios_##n##_master_bus_config[] = { \
DT_FOREACH_CHILD_STATUS_OKAY(DT_INST_CHILD(n, master_bus), \
NXP_S32_EMIOS_MASTER_BUS_CONFIG) \
};
#define NXP_S32_EMIOS_GENERATE_CONFIG(n) \
NXP_S32_EMIOS_GENERATE_GLOBAL_CONFIG(n) \
NXP_S32_EMIOS_GENERATE_MASTER_BUS_CONFIG(n) \
const Emios_Mcl_Ip_ConfigType nxp_s32_emios_##n##_mcl_config = { \
.channelsNumber = ARRAY_SIZE(nxp_s32_emios_##n##_master_bus_config), \
.emiosGlobalConfig = &nxp_s32_emios_##n##_global_config, \
.masterBusConfig = &nxp_s32_emios_##n##_master_bus_config \
};
#define NXP_S32_EMIOS_INIT_DEVICE(n) \
NXP_S32_EMIOS_GENERATE_CONFIG(n) \
const struct nxp_s32_emios_config nxp_s32_emios_##n##_config = { \
.instance = NXP_S32_EMIOS_GET_INSTANCE(n), \
.mcl_info = (Emios_Mcl_Ip_ConfigType *)&nxp_s32_emios_##n##_mcl_config, \
}; \
DEVICE_DT_INST_DEFINE(n, \
&nxp_s32_emios_init, \
NULL, \
NULL, \
&nxp_s32_emios_##n##_config, \
POST_KERNEL, \
CONFIG_NXP_S32_EMIOS_INIT_PRIORITY, \
NULL);
DT_INST_FOREACH_STATUS_OKAY(NXP_S32_EMIOS_INIT_DEVICE)