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:
parent
eee426742b
commit
e5e2f2fad8
7 changed files with 376 additions and 0 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
8
drivers/misc/nxp_s32_emios/CMakeLists.txt
Normal file
8
drivers/misc/nxp_s32_emios/CMakeLists.txt
Normal 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
|
||||
)
|
22
drivers/misc/nxp_s32_emios/Kconfig
Normal file
22
drivers/misc/nxp_s32_emios/Kconfig
Normal 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
|
105
drivers/misc/nxp_s32_emios/nxp_s32_emios.c
Normal file
105
drivers/misc/nxp_s32_emios/nxp_s32_emios.c
Normal 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)
|
|
@ -597,6 +597,144 @@
|
|||
interrupt-names = "common", "tx", "rx", "safety";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
emios0: emios@40088000 {
|
||||
compatible = "nxp,s32-emios";
|
||||
reg = <0x40088000 0x4000>;
|
||||
clocks = <&clock NXP_S32_EMIOS0_CLK>;
|
||||
interrupts = <61 0>, <62 0>, <63 0>,
|
||||
<64 0>, <65 0>, <66 0>;
|
||||
status = "disabled";
|
||||
|
||||
master_bus {
|
||||
emios0_bus_a: emios0_bus_a {
|
||||
channel = <23>;
|
||||
bus-type = "BUS_A";
|
||||
channel-mask = <0x07FFFFF>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
emios0_bus_b: emios0_bus_b {
|
||||
channel = <0>;
|
||||
bus-type = "BUS_B";
|
||||
channel-mask = <0x00000FE>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
emios0_bus_c: emios0_bus_c {
|
||||
channel = <8>;
|
||||
bus-type = "BUS_C";
|
||||
channel-mask = <0x0000FE00>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
emios0_bus_d: emios0_bus_d {
|
||||
channel = <16>;
|
||||
bus-type = "BUS_D";
|
||||
channel-mask = <0x00FE0000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
emios0_bus_f: emios0_bus_f {
|
||||
channel = <22>;
|
||||
bus-type = "BUS_F";
|
||||
channel-mask = <0x0BFFFFF>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
emios1: emios@4008c000 {
|
||||
compatible = "nxp,s32-emios";
|
||||
reg = <0x4008c000 0x4000>;
|
||||
clocks = <&clock NXP_S32_EMIOS1_CLK>;
|
||||
interrupts = <69 0>, <70 0>, <71 0>,
|
||||
<72 0>, <73 0>, <74 0>;
|
||||
status = "disabled";
|
||||
|
||||
master_bus {
|
||||
emios1_bus_a: emios1_bus_a {
|
||||
channel = <23>;
|
||||
bus-type = "BUS_A";
|
||||
channel-mask = <0x07FFFFF>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
emios1_bus_b: emios1_bus_b {
|
||||
channel = <0>;
|
||||
bus-type = "BUS_B";
|
||||
channel-mask = <0x00000FE>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
emios1_bus_c: emios1_bus_c {
|
||||
channel = <8>;
|
||||
bus-type = "BUS_C";
|
||||
channel-mask = <0x0000FE00>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
emios1_bus_d: emios1_bus_d {
|
||||
channel = <16>;
|
||||
bus-type = "BUS_D";
|
||||
channel-mask = <0x00FE0000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
emios1_bus_f: emios1_bus_f {
|
||||
channel = <22>;
|
||||
channel-mask = <0x0BFFFFF>;
|
||||
bus-type = "BUS_F";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
emios2: emios@40090000 {
|
||||
compatible = "nxp,s32-emios";
|
||||
reg = <0x40090000 0x4000>;
|
||||
clocks = <&clock NXP_S32_EMIOS2_CLK>;
|
||||
interrupts = <77 0>, <78 0>, <79 0>,
|
||||
<80 0>, <81 0>, <82 0>;
|
||||
status = "disabled";
|
||||
|
||||
master_bus {
|
||||
emios2_bus_a: emios2_bus_a {
|
||||
channel = <23>;
|
||||
bus-type = "BUS_A";
|
||||
channel-mask = <0x07FFFFF>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
emios2_bus_b: emios2_bus_b {
|
||||
channel = <0>;
|
||||
bus-type = "BUS_B";
|
||||
channel-mask = <0x00000FE>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
emios2_bus_c: emios2_bus_c {
|
||||
channel = <8>;
|
||||
bus-type = "BUS_C";
|
||||
channel-mask = <0x0000FE00>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
emios2_bus_d: emios2_bus_d {
|
||||
channel = <16>;
|
||||
bus-type = "BUS_D";
|
||||
channel-mask = <0x00FE0000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
emios2_bus_f: emios2_bus_f {
|
||||
channel = <22>;
|
||||
bus-type = "BUS_F";
|
||||
channel-mask = <0x0BFFFFF>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
101
dts/bindings/misc/nxp,s32-emios.yaml
Normal file
101
dts/bindings/misc/nxp,s32-emios.yaml
Normal file
|
@ -0,0 +1,101 @@
|
|||
# Copyright 2023 NXP
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
NXP S32 Enhanced Modular IO SubSystem (eMIOS) node for S32 SoCs.
|
||||
eMIOS provides independent unified channels (UCs), some of channels
|
||||
have internal counter that either can be used independently or used
|
||||
as a reference timebase (master bus) for other channels.
|
||||
|
||||
compatible: "nxp,s32-emios"
|
||||
|
||||
include: [base.yaml]
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
||||
|
||||
clock-divider:
|
||||
type: int
|
||||
required: true
|
||||
description: |
|
||||
Clock divider value for the global prescaler. Could be in range [1 ... 256]
|
||||
|
||||
child-binding:
|
||||
child-binding:
|
||||
description: |
|
||||
Node for eMIOS master bus. Each channel is capable to become a master bus has
|
||||
a node defined in root devicetree but is disabled by default. To allow using
|
||||
the master bus, the devicetree node should be enabled and dts properties
|
||||
should be configured as required by application.
|
||||
|
||||
For example, to enable bus A of eMIOS instance 0 that can be used as timebase
|
||||
for channels from 0 to 22, freezed in debug mode:
|
||||
master_bus {
|
||||
emios0_bus_a: emios0_bus_a {
|
||||
channel = <23>;
|
||||
bus-type = "BUS_A";
|
||||
channel-mask = <0x07FFFFF>;
|
||||
prescaler = <1>;
|
||||
period = <65535>;
|
||||
mode = <MCB_UP_COUNTER>;
|
||||
freeze;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
properties:
|
||||
channel:
|
||||
type: int
|
||||
required: true
|
||||
description: |
|
||||
Channel identifier for the master bus.
|
||||
|
||||
channel-mask:
|
||||
type: int
|
||||
required: true
|
||||
description: |
|
||||
A channel mask for channels that by hardware design can use this master bus
|
||||
as timebase for the operation, lsb is channel 0. The mask bit for this master bus
|
||||
must always 0 because a master bus should not do other thing than a base timer.
|
||||
|
||||
prescaler:
|
||||
type: int
|
||||
required: true
|
||||
description: |
|
||||
Clock divider value for internal UC prescaler.
|
||||
Clock for internal counter = (eMIOS clock / global prescaler) / internal prescaler.
|
||||
enum: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
|
||||
|
||||
bus-type:
|
||||
type: string
|
||||
required: true
|
||||
description: |
|
||||
Master bus type.
|
||||
enum:
|
||||
- "BUS_A"
|
||||
- "BUS_B"
|
||||
- "BUS_C"
|
||||
- "BUS_D"
|
||||
- "BUS_E"
|
||||
- "BUS_F"
|
||||
|
||||
mode:
|
||||
type: string
|
||||
required: true
|
||||
description: |
|
||||
Master bus mode.
|
||||
enum:
|
||||
- "MCB_UP_COUNTER"
|
||||
- "MCB_UP_DOWN_COUNTER"
|
||||
|
||||
period:
|
||||
type: int
|
||||
required: true
|
||||
description: |
|
||||
Default period (in ticks) for master bus at boot time. This determines PWM period
|
||||
for channels use this bus as reference timebase. Could be in range [2 ... 65535]
|
||||
|
||||
freeze:
|
||||
type: boolean
|
||||
description: Freeze internal counter when the chip enters Debug mode.
|
Loading…
Add table
Add a link
Reference in a new issue