drivers: sensor: qdec_s32: Add QDEC support for S32

Add code to configure and program Lcu, Trgmux and Emios_Icu IPs to
get the the rotations by the motor in radians.

Co-authored-by: Benjamin Perseghetti <bperseghetti@rudislabs.com>
Co-authored-by: Peter van der Perk <peter.vanderperk@nxp.com>
Co-authored-by: Mayank Mahajan <mayankmahajan.x@nxp.com>
Signed-off-by: Sumit Batra <sumit.batra@nxp.com>
diff --git a/boards/arm/mr_canhubk3/mr_canhubk3-pinctrl.dtsi b/boards/arm/mr_canhubk3/mr_canhubk3-pinctrl.dtsi
index 0b2906f..e057aeb 100644
--- a/boards/arm/mr_canhubk3/mr_canhubk3-pinctrl.dtsi
+++ b/boards/arm/mr_canhubk3/mr_canhubk3-pinctrl.dtsi
@@ -287,7 +287,6 @@
 			pinmux = <PTB12_EMIOS_0_CH0_X_O>, <PTB13_EMIOS_0_CH1_G_O>,
 				<PTB14_EMIOS_0_CH2_G_O>, <PTB15_EMIOS_0_CH3_G_O>,
 				<PTB16_EMIOS_0_CH4_G_O>, <PTB17_EMIOS_0_CH5_G_O>,
-				<PTA17_EMIOS_0_CH6_G_O>, <PTE7_EMIOS_0_CH7_G_O>,
 				<PTE14_EMIOS_0_CH19_Y_O>;
 			output-enable;
 		};
@@ -300,4 +299,14 @@
 			output-enable;
 		};
 	};
+
+	qdec_s32: qdec_s32 {
+		group1 {
+			pinmux = <PTB2_TRGMUX_IN3>,
+				<PTB3_TRGMUX_IN2>,
+				<TRGMUX_INT_OUT37_EMIOS_0_CH6_G>,
+				<TRGMUX_INT_OUT38_EMIOS_0_CH7_G>;
+			input-enable;
+		};
+	};
 };
diff --git a/boards/arm/mr_canhubk3/mr_canhubk3.dts b/boards/arm/mr_canhubk3/mr_canhubk3.dts
index 50b7233..97bca14 100644
--- a/boards/arm/mr_canhubk3/mr_canhubk3.dts
+++ b/boards/arm/mr_canhubk3/mr_canhubk3.dts
@@ -11,6 +11,7 @@
 #include <freq.h>
 #include <dt-bindings/pwm/pwm.h>
 #include "mr_canhubk3-pinctrl.dtsi"
+#include <zephyr/dt-bindings/sensor/qdec_nxp_s32.h>
 
 / {
 	model = "NXP MR-CANHUBK3";
@@ -42,6 +43,7 @@
 		green-pwm-led = &user_led1_green_pwm;
 		blue-pwm-led = &user_led1_blue_pwm;
 		pwm-led0 = &user_led1_blue_pwm;
+		qdec0 = &qdec0;
 	};
 
 	leds {
@@ -77,6 +79,39 @@
 		};
 	};
 
+	qdec0: qdec0 {
+		compatible = "nxp,qdec-s32";
+		pinctrl-0 = <&qdec_s32>;
+		pinctrl-names = "default";
+		micro-ticks-per-rev = <685440000>;
+		status = "okay";
+		trgmux = <&trgmux>;
+		trgmux-io-config =
+		<0 TRGMUX_IP_OUTPUT_EMIOS0_CH5_9_IPP_IND_CH6 TRGMUX_IP_INPUT_LCU1_LC0_OUT_I2>,
+		<1 TRGMUX_IP_OUTPUT_EMIOS0_CH5_9_IPP_IND_CH7 TRGMUX_IP_INPUT_LCU1_LC0_OUT_I3>,
+		<2 TRGMUX_IP_OUTPUT_LCU1_0_INP_I0            TRGMUX_IP_INPUT_SIUL2_IN2>,
+		<3 TRGMUX_IP_OUTPUT_LCU1_0_INP_I1            TRGMUX_IP_INPUT_SIUL2_IN3>;
+		lcu = <&lcu1>;
+		lcu-input-idx =
+		<LCU_IP_IN_0 LCU_IP_IN_1
+		 LCU_IP_IN_2 LCU_IP_IN_3>;
+		lcu-mux-sel =
+		<LCU_IP_MUX_SEL_LU_IN_0 LCU_IP_MUX_SEL_LU_IN_1
+		 LCU_IP_MUX_SEL_LU_OUT_0 LCU_IP_MUX_SEL_LU_OUT_1>;
+		lcu-output-filter-config =
+			/* LCU Out HW ID, Rise Filter, Fall Filter */
+			<0 5 5>, /* LCU O0 */
+			<1 5 5>, /* LCU O1 */
+			<2 2 2>, /* LCU O2 */
+			<3 2 2>; /* LCU O3 */
+		emios = <&emios0>;
+		/*
+		 * eMios channel numbers for qdec should be beyond the channel numbers
+		 * used by the emios pwm
+		 */
+		emios-channels = <6 7>;
+	};
+
 	gpio_keys {
 		compatible = "gpio-keys";
 		user_button_1: button_0 {
@@ -501,24 +536,6 @@
 			polarity = "ACTIVE_HIGH";
 		};
 
-		pwm_6 {
-			channel = <6>;
-			pwm-mode = "OPWFMB";
-			period = <65535>;
-			duty-cycle = <0>;
-			prescaler = <8>;
-			polarity = "ACTIVE_HIGH";
-		};
-
-		pwm_7 {
-			channel = <7>;
-			pwm-mode = "OPWFMB";
-			period = <65535>;
-			duty-cycle = <0>;
-			prescaler = <8>;
-			polarity = "ACTIVE_HIGH";
-		};
-
 		rgb_red {
 			channel = <19>;
 			master-bus = <&emios0_bus_a>;
@@ -576,6 +593,14 @@
 	};
 };
 
+&lcu1 {
+	status = "okay";
+};
+
+&trgmux {
+	status = "okay";
+};
+
 &edma0 {
 	status = "okay";
 };
diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt
index 76bb17b..afa200a 100644
--- a/drivers/sensor/CMakeLists.txt
+++ b/drivers/sensor/CMakeLists.txt
@@ -112,6 +112,7 @@
 add_subdirectory_ifdef(CONFIG_PCNT_ESP32 pcnt_esp32)
 add_subdirectory_ifdef(CONFIG_PMS7003 pms7003)
 add_subdirectory_ifdef(CONFIG_QDEC_MCUX qdec_mcux)
+add_subdirectory_ifdef(CONFIG_QDEC_NXP_S32 qdec_nxp_s32)
 add_subdirectory_ifdef(CONFIG_QDEC_NRFX qdec_nrfx)
 add_subdirectory_ifdef(CONFIG_QDEC_SAM qdec_sam)
 add_subdirectory_ifdef(CONFIG_QDEC_STM32 qdec_stm32)
diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig
index fba7501..7e45474 100644
--- a/drivers/sensor/Kconfig
+++ b/drivers/sensor/Kconfig
@@ -189,6 +189,7 @@
 source "drivers/sensor/pcnt_esp32/Kconfig"
 source "drivers/sensor/pms7003/Kconfig"
 source "drivers/sensor/qdec_mcux/Kconfig"
+source "drivers/sensor/qdec_nxp_s32/Kconfig"
 source "drivers/sensor/qdec_nrfx/Kconfig"
 source "drivers/sensor/qdec_sam/Kconfig"
 source "drivers/sensor/qdec_stm32/Kconfig"
diff --git a/drivers/sensor/qdec_nxp_s32/CMakeLists.txt b/drivers/sensor/qdec_nxp_s32/CMakeLists.txt
new file mode 100644
index 0000000..a3065a3
--- /dev/null
+++ b/drivers/sensor/qdec_nxp_s32/CMakeLists.txt
@@ -0,0 +1,6 @@
+# Copyright 2023 NXP
+# SPDX-License-Identifier: Apache-2.0
+
+zephyr_library()
+
+zephyr_library_sources(qdec_nxp_s32.c)
diff --git a/drivers/sensor/qdec_nxp_s32/Kconfig b/drivers/sensor/qdec_nxp_s32/Kconfig
new file mode 100644
index 0000000..4250d9b
--- /dev/null
+++ b/drivers/sensor/qdec_nxp_s32/Kconfig
@@ -0,0 +1,10 @@
+# Copyright 2023 NXP
+# SPDX-License-Identifier: Apache-2.0
+
+config QDEC_NXP_S32
+	bool "NXP Quad Decoder S32 drivers"
+	default y
+	depends on DT_HAS_NXP_QDEC_S32_ENABLED
+	select NXP_S32_EMIOS
+	help
+	  Enable drivers for NXP S32 QUADRATURE DECODER
diff --git a/drivers/sensor/qdec_nxp_s32/qdec_nxp_s32.c b/drivers/sensor/qdec_nxp_s32/qdec_nxp_s32.c
new file mode 100644
index 0000000..31d6297
--- /dev/null
+++ b/drivers/sensor/qdec_nxp_s32/qdec_nxp_s32.c
@@ -0,0 +1,451 @@
+/*
+ * Copyright 2023 NXP
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <errno.h>
+#include <stdint.h>
+
+#include <zephyr/drivers/pinctrl.h>
+#include <zephyr/drivers/sensor.h>
+#include <zephyr/logging/log.h>
+#include <zephyr/sys/arch_interface.h>
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#define EMIOS_CHANNEL_COUNT 2U
+#define EMIOS_CW_CH_IDX     0
+#define EMIOS_CCW_CH_IDX    1
+
+/* LCU LUT control values for each of the 4 LC outputs */
+/* These values decide the direction of motor rotation */
+#define LCU_O0_LUT 0xAAAA
+#define LCU_O1_LUT 0xCCCC
+#define LCU_O2_LUT 0x4182
+#define LCU_O3_LUT 0x2814
+
+LOG_MODULE_REGISTER(nxp_qdec_s32, CONFIG_SENSOR_LOG_LEVEL);
+
+#include <Emios_Icu_Ip.h>
+#include <Trgmux_Ip.h>
+#include <Lcu_Ip.h>
+
+#define DT_DRV_COMPAT nxp_qdec_s32
+
+typedef void (*emios_callback_t)(void);
+
+/* Configuration variables from eMIOS Icu driver */
+extern eMios_Icu_Ip_ChStateType eMios_Icu_Ip_ChState[EMIOS_ICU_IP_NUM_OF_CHANNELS_USED];
+extern uint8 eMios_Icu_Ip_IndexInChState[EMIOS_ICU_IP_INSTANCE_COUNT][EMIOS_ICU_IP_NUM_OF_CHANNELS];
+
+struct qdec_s32_config {
+	uint8_t emios_inst;
+	uint8_t emios_channels[EMIOS_CHANNEL_COUNT];
+	const struct pinctrl_dev_config *pincfg;
+
+	const Trgmux_Ip_InitType *trgmux_config;
+
+	const Lcu_Ip_InitType *lcu_config;
+	emios_callback_t emios_cw_overflow_cb;
+	emios_callback_t emios_ccw_overflow_cb;
+};
+
+struct qdec_s32_data {
+	uint32_t counter_CW;
+	uint32_t counter_CCW;
+	int32_t abs_counter;
+	float micro_ticks_per_rev;
+	uint32_t ticks_per_sec;
+	uint32_t emios_cw_overflow_count;
+	uint32_t emios_ccw_overflow_count;
+};
+
+static void qdec_emios_overflow_count_cw_callback(const struct device *dev)
+{
+	struct qdec_s32_data *data = dev->data;
+
+	data->emios_cw_overflow_count++;
+}
+
+static void qdec_emios_overflow_count_ccw_callback(const struct device *dev)
+{
+	struct qdec_s32_data *data = dev->data;
+
+	data->emios_ccw_overflow_count++;
+}
+
+static int qdec_s32_fetch(const struct device *dev, enum sensor_channel ch)
+{
+	const struct qdec_s32_config *config = dev->config;
+	struct qdec_s32_data *data = dev->data;
+
+	if (ch != SENSOR_CHAN_ALL) {
+		return -ENOTSUP;
+	}
+
+	data->counter_CW = (uint32_t)(Emios_Icu_Ip_GetEdgeNumbers(
+	config->emios_inst, config->emios_channels[EMIOS_CW_CH_IDX])); /* CW counter */
+	data->counter_CCW = (uint32_t)(Emios_Icu_Ip_GetEdgeNumbers(
+	config->emios_inst, config->emios_channels[EMIOS_CCW_CH_IDX]));/* CCW counter*/
+
+	data->abs_counter = (int32_t)(
+		+(data->counter_CW  + EMIOS_ICU_IP_COUNTER_MASK *
+			data->emios_cw_overflow_count)
+		-(data->counter_CCW + EMIOS_ICU_IP_COUNTER_MASK *
+			data->emios_ccw_overflow_count));
+
+	LOG_DBG("ABS_COUNT = %d CW = %u OverFlow_CW = %u CCW = %u Overflow_CCW = %u",
+		data->abs_counter, data->counter_CW,
+		data->emios_cw_overflow_count,
+		data->counter_CCW, data->emios_ccw_overflow_count);
+
+	return 0;
+}
+
+static int qdec_s32_ch_get(const struct device *dev, enum sensor_channel ch,
+		struct sensor_value *val)
+{
+	struct qdec_s32_data *data = dev->data;
+
+	double rotation = (data->abs_counter * 2.0 * M_PI) / data->micro_ticks_per_rev;
+
+	switch (ch) {
+	case SENSOR_CHAN_ROTATION:
+		sensor_value_from_double(val, rotation);
+		break;
+	default:
+		return -ENOTSUP;
+	}
+
+	return 0;
+}
+
+static const struct sensor_driver_api qdec_s32_api = {
+	.sample_fetch = &qdec_s32_fetch,
+	.channel_get = &qdec_s32_ch_get,
+};
+
+static int qdec_s32_initialize(const struct device *dev)
+{
+	const struct qdec_s32_config *config = dev->config;
+	uint8_t emios_inst, emios_hw_ch_cw, emios_hw_ch_ccw;
+
+	pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
+
+	if (Trgmux_Ip_Init(config->trgmux_config)) {
+		LOG_ERR("Could not initialize Trgmux");
+		return -EINVAL;
+	}
+
+	LOG_DBG("TRGMUX ACCESS Input[0] =%d Output[0]=%d",
+		config->trgmux_config->paxLogicTrigger[0]->Input,
+		config->trgmux_config->paxLogicTrigger[0]->Output);
+
+	if (Lcu_Ip_Init(config->lcu_config)) {
+		LOG_ERR("Could not initialize Lcu");
+		return -EINVAL;
+	}
+
+	/* Unmask relevant LCU OUT Channels */
+	Lcu_Ip_SyncOutputValueType EncLcuEnable[4U];
+
+	EncLcuEnable[0].LogicOutputId = LCU_LOGIC_OUTPUT_0;
+	EncLcuEnable[0].Value = 1U;
+	EncLcuEnable[1].LogicOutputId = LCU_LOGIC_OUTPUT_1;
+	EncLcuEnable[1].Value = 1U;
+	EncLcuEnable[2].LogicOutputId = LCU_LOGIC_OUTPUT_2;
+	EncLcuEnable[2].Value = 1U;
+	EncLcuEnable[3].LogicOutputId = LCU_LOGIC_OUTPUT_3;
+	EncLcuEnable[3].Value = 1U;
+	Lcu_Ip_SetSyncOutputEnable(EncLcuEnable, 4U);
+
+	emios_inst = config->emios_inst;
+	emios_hw_ch_cw =  config->emios_channels[EMIOS_CW_CH_IDX];
+	emios_hw_ch_ccw =  config->emios_channels[EMIOS_CCW_CH_IDX];
+
+	/* Initialize the positions of the eMios hw channels used for QDEC
+	 * to be beyond the eMios pwm hw channels. Currently only pwm and qdec
+	 * are using the eMios channels so qdec ones are the last two.
+	 */
+	eMios_Icu_Ip_IndexInChState[emios_inst][emios_hw_ch_cw]
+		= EMIOS_ICU_IP_NUM_OF_CHANNELS_USED - 2;
+	eMios_Icu_Ip_IndexInChState[emios_inst][emios_hw_ch_ccw]
+		= EMIOS_ICU_IP_NUM_OF_CHANNELS_USED - 1;
+
+	/* Set Overflow Notification for eMIOS channels meant
+	 * for Clockwise and Counterclock rotation counters
+	 */
+	eMios_Icu_Ip_ChState[eMios_Icu_Ip_IndexInChState[emios_inst][emios_hw_ch_cw]]
+		.eMiosOverflowNotification = config->emios_cw_overflow_cb;
+	eMios_Icu_Ip_ChState[eMios_Icu_Ip_IndexInChState[emios_inst][emios_hw_ch_ccw]]
+		.eMiosOverflowNotification = config->emios_ccw_overflow_cb;
+
+	Emios_Icu_Ip_SetInitialCounterValue(
+		config->emios_inst, config->emios_channels[EMIOS_CW_CH_IDX], (uint32_t)0x1U);
+	Emios_Icu_Ip_SetInitialCounterValue(
+		config->emios_inst, config->emios_channels[EMIOS_CCW_CH_IDX], (uint32_t)0x1U);
+
+	Emios_Icu_Ip_SetMaxCounterValue(config->emios_inst,
+		config->emios_channels[EMIOS_CW_CH_IDX],
+		EMIOS_ICU_IP_COUNTER_MASK);
+	Emios_Icu_Ip_SetMaxCounterValue(config->emios_inst,
+		config->emios_channels[EMIOS_CCW_CH_IDX],
+		EMIOS_ICU_IP_COUNTER_MASK);
+
+	/* This API sets MCB/EMIOS_ICU_MODE_EDGE_COUNTER mode */
+	Emios_Icu_Ip_EnableEdgeCount(config->emios_inst, config->emios_channels[EMIOS_CW_CH_IDX]);
+	Emios_Icu_Ip_EnableEdgeCount(config->emios_inst, config->emios_channels[EMIOS_CCW_CH_IDX]);
+
+	LOG_DBG("Init complete");
+
+	return 0;
+}
+
+#define EMIOS_NXP_S32_MCB_OVERFLOW_CALLBACK(n)							\
+	static void qdec##n##_emios_overflow_count_cw_callback(void)				\
+	{											\
+		qdec_emios_overflow_count_cw_callback(DEVICE_DT_INST_GET(n));			\
+	}											\
+												\
+	static void qdec##n##_emios_overflow_count_ccw_callback(void)				\
+	{											\
+		qdec_emios_overflow_count_ccw_callback(DEVICE_DT_INST_GET(n));			\
+	}
+
+#define EMIOS_NXP_S32_INSTANCE_CHECK(idx, node_id)						\
+	((DT_REG_ADDR(node_id) == IP_EMIOS_##idx##_BASE) ? idx : 0)
+
+#define EMIOS_NXP_S32_GET_INSTANCE(node_id)							\
+	LISTIFY(__DEBRACKET eMIOS_INSTANCE_COUNT, EMIOS_NXP_S32_INSTANCE_CHECK, (|), node_id)
+
+#define LCU_NXP_S32_INSTANCE_CHECK(idx, node_id)						\
+	((DT_REG_ADDR(node_id) == IP_LCU_##idx##_BASE) ? idx : 0)
+
+#define LCU_NXP_S32_GET_INSTANCE(node_id)							\
+	LISTIFY(__DEBRACKET LCU_INSTANCE_COUNT, LCU_NXP_S32_INSTANCE_CHECK, (|), node_id)
+
+#define TRGMUX_NXP_S32_INSTANCE_CHECK(node_id)							\
+	((DT_REG_ADDR(node_id) == IP_TRGMUX_BASE) ? 0 : -1)
+
+#define TRGMUX_NXP_S32_GET_INSTANCE(node_id)	TRGMUX_NXP_S32_INSTANCE_CHECK(node_id)
+
+/* LCU Logic Input Configuration */
+#define LogicInputCfg_Common(n, mux_sel_idx)							\
+	{											\
+		.MuxSel = DT_INST_PROP_BY_IDX(n, lcu_mux_sel, mux_sel_idx),			\
+		.SwSynMode = LCU_IP_SW_SYNC_IMMEDIATE,						\
+		.SwValue = LCU_IP_SW_OVERRIDE_LOGIC_LOW,					\
+	};
+#define LogicInput_Config_Common(n, hw_lc_input_id, logic_input_n_cfg)				\
+	{											\
+		.xLogicInputId = {								\
+			.HwInstId = LCU_NXP_S32_GET_INSTANCE(DT_INST_PHANDLE(n, lcu)),		\
+			.HwLcInputId = DT_INST_PROP_BY_IDX(n, lcu_input_idx, hw_lc_input_id),	\
+		},										\
+		.pxLcInputConfig = &logic_input_n_cfg,						\
+	};
+
+/* LCU Logic Output Configuration */
+#define LogicOutputCfg_Common(En_Debug_Mode, Lut_Control, Lut_Rise_Filt, Lut_Fall_Filt)		\
+	{											\
+		.EnDebugMode = (boolean)En_Debug_Mode,						\
+		.LutControl = Lut_Control,							\
+		.LutRiseFilt = Lut_Rise_Filt,							\
+		.LutFallFilt = Lut_Fall_Filt,							\
+		.EnLutDma = (boolean)FALSE,							\
+		.EnForceDma = (boolean)FALSE,							\
+		.EnLutInt = (boolean)FALSE,							\
+		.EnForceInt = (boolean)FALSE,							\
+		.InvertOutput = (boolean)FALSE,							\
+		.ForceSignalSel = 0U,								\
+		.ClearForceMode = LCU_IP_CLEAR_FORCE_SIGNAL_IMMEDIATE,				\
+		.ForceSyncSel = LCU_IP_SYNC_SEL_INPUT0,						\
+	};
+#define LogicOutput_Config_Common(n, logic_output_cfg, hw_lc_output_id)				\
+	{											\
+		.xLogicOutputId = {								\
+			.HwInstId = LCU_NXP_S32_GET_INSTANCE(DT_INST_PHANDLE(n, lcu)),		\
+			.HwLcOutputId = hw_lc_output_id,					\
+			.IntCallback = NULL_PTR,						\
+		},										\
+		.pxLcOutputConfig = &logic_output_cfg,						\
+	};
+
+#define LCU_IP_INIT_CONFIG(n)									\
+	const Lcu_Ip_LogicInputConfigType LogicInput##n##_0_Cfg =				\
+		LogicInputCfg_Common(n, 0)							\
+	const Lcu_Ip_LogicInputConfigType LogicInput##n##_1_Cfg =				\
+		LogicInputCfg_Common(n, 1)							\
+	const Lcu_Ip_LogicInputConfigType LogicInput##n##_2_Cfg =				\
+		LogicInputCfg_Common(n, 2)							\
+	const Lcu_Ip_LogicInputConfigType LogicInput##n##_3_Cfg =				\
+		LogicInputCfg_Common(n, 3)							\
+												\
+	const Lcu_Ip_LogicInputType LogicInput##n##_0_Config =					\
+		LogicInput_Config_Common(n, 0, LogicInput##n##_0_Cfg)				\
+	const Lcu_Ip_LogicInputType LogicInput##n##_1_Config =					\
+		LogicInput_Config_Common(n, 1, LogicInput##n##_1_Cfg)				\
+	const Lcu_Ip_LogicInputType LogicInput##n##_2_Config =					\
+		LogicInput_Config_Common(n, 2, LogicInput##n##_2_Cfg)				\
+	const Lcu_Ip_LogicInputType LogicInput##n##_3_Config =					\
+		LogicInput_Config_Common(n, 3, LogicInput##n##_3_Cfg)				\
+												\
+	const Lcu_Ip_LogicInputType								\
+		*const Lcu_Ip_ppxLogicInputArray##n##_Config[LCU_IP_NOF_CFG_LOGIC_INPUTS] = {	\
+			&LogicInput##n##_0_Config,						\
+			&LogicInput##n##_1_Config,						\
+			&LogicInput##n##_2_Config,						\
+			&LogicInput##n##_3_Config,						\
+		};										\
+												\
+	const Lcu_Ip_LogicOutputConfigType LogicOutput##n##_0_Cfg = LogicOutputCfg_Common(	\
+		LCU_IP_DEBUG_DISABLE, LCU_O0_LUT,						\
+		DT_INST_PROP_BY_IDX(n, lcu_output_filter_config, 1),				\
+		DT_INST_PROP_BY_IDX(n, lcu_output_filter_config, 2))				\
+	const Lcu_Ip_LogicOutputConfigType LogicOutput##n##_1_Cfg = LogicOutputCfg_Common(	\
+		LCU_IP_DEBUG_DISABLE, LCU_O1_LUT,						\
+		DT_INST_PROP_BY_IDX(n, lcu_output_filter_config, 4),				\
+		DT_INST_PROP_BY_IDX(n, lcu_output_filter_config, 5))				\
+	const Lcu_Ip_LogicOutputConfigType LogicOutput##n##_2_Cfg = LogicOutputCfg_Common(	\
+		LCU_IP_DEBUG_ENABLE, LCU_O2_LUT,						\
+		DT_INST_PROP_BY_IDX(n, lcu_output_filter_config, 7),				\
+		DT_INST_PROP_BY_IDX(n, lcu_output_filter_config, 8))				\
+	const Lcu_Ip_LogicOutputConfigType LogicOutput##n##_3_Cfg = LogicOutputCfg_Common(	\
+		LCU_IP_DEBUG_ENABLE, LCU_O3_LUT,						\
+		DT_INST_PROP_BY_IDX(n, lcu_output_filter_config, 10),				\
+		DT_INST_PROP_BY_IDX(n, lcu_output_filter_config, 11))				\
+												\
+	const Lcu_Ip_LogicOutputType LogicOutput##n##_0_Config =				\
+		LogicOutput_Config_Common(n, LogicOutput##n##_0_Cfg,				\
+		DT_INST_PROP_BY_IDX(n, lcu_output_filter_config, 0))				\
+	const Lcu_Ip_LogicOutputType LogicOutput##n##_1_Config =				\
+		LogicOutput_Config_Common(n, LogicOutput##n##_1_Cfg,				\
+		DT_INST_PROP_BY_IDX(n, lcu_output_filter_config, 3))				\
+	const Lcu_Ip_LogicOutputType LogicOutput##n##_2_Config =				\
+		LogicOutput_Config_Common(n, LogicOutput##n##_2_Cfg,				\
+		DT_INST_PROP_BY_IDX(n, lcu_output_filter_config, 6))				\
+	const Lcu_Ip_LogicOutputType LogicOutput##n##_3_Config =				\
+		LogicOutput_Config_Common(n, LogicOutput##n##_3_Cfg,				\
+		DT_INST_PROP_BY_IDX(n, lcu_output_filter_config, 9))				\
+												\
+	const Lcu_Ip_LogicOutputType								\
+		*const Lcu_Ip_ppxLogicOutputArray##n##_Config[LCU_IP_NOF_CFG_LOGIC_OUTPUTS] = {	\
+			&LogicOutput##n##_0_Config,						\
+			&LogicOutput##n##_1_Config,						\
+			&LogicOutput##n##_2_Config,						\
+			&LogicOutput##n##_3_Config,						\
+		};										\
+												\
+	const Lcu_Ip_LogicInputConfigType Lcu_Ip_LogicInputResetConfig##n = {			\
+		.MuxSel = LCU_IP_MUX_SEL_LOGIC_0,						\
+		.SwSynMode = LCU_IP_SW_SYNC_IMMEDIATE,						\
+		.SwValue = LCU_IP_SW_OVERRIDE_LOGIC_LOW,					\
+	};											\
+												\
+	const Lcu_Ip_LogicOutputConfigType Lcu_Ip_LogicOutputResetConfig##n =			\
+		LogicOutputCfg_Common(LCU_IP_DEBUG_DISABLE, 0U, 0U, 0U)				\
+												\
+	const Lcu_Ip_LogicInstanceType LcuLogicInstance##n##_0_Config = {			\
+		.HwInstId = LCU_NXP_S32_GET_INSTANCE(DT_INST_PHANDLE(n, lcu)),			\
+		.NumLogicCellConfig = 0U,							\
+		.ppxLogicCellConfigArray = NULL_PTR,						\
+		.OperationMode = LCU_IP_INTERRUPT_MODE,						\
+	};											\
+	const Lcu_Ip_LogicInstanceType								\
+	*const Lcu_Ip_ppxLogicInstanceArray##n##_Config[LCU_IP_NOF_CFG_LOGIC_INSTANCES] = {	\
+			&LcuLogicInstance##n##_0_Config,					\
+		};										\
+												\
+	Lcu_Ip_HwOutputStateType HwOutput##n##_0_State_Config;					\
+	Lcu_Ip_HwOutputStateType HwOutput##n##_1_State_Config;					\
+	Lcu_Ip_HwOutputStateType HwOutput##n##_2_State_Config;					\
+	Lcu_Ip_HwOutputStateType HwOutput##n##_3_State_Config;					\
+	Lcu_Ip_HwOutputStateType								\
+		*Lcu_Ip_ppxHwOutputStateArray##n##_Config[LCU_IP_NOF_CFG_LOGIC_OUTPUTS] = {	\
+			&HwOutput##n##_0_State_Config,						\
+			&HwOutput##n##_1_State_Config,						\
+			&HwOutput##n##_2_State_Config,						\
+			&HwOutput##n##_3_State_Config,						\
+	};											\
+												\
+	const Lcu_Ip_InitType Lcu_Ip_Init_Config##n = {						\
+		.ppxHwOutputStateArray = &Lcu_Ip_ppxHwOutputStateArray##n##_Config[0],		\
+		.ppxLogicInstanceConfigArray = &Lcu_Ip_ppxLogicInstanceArray##n##_Config[0],	\
+		.pxLogicOutputResetConfigArray = &Lcu_Ip_LogicOutputResetConfig##n,		\
+		.pxLogicInputResetConfigArray = &Lcu_Ip_LogicInputResetConfig##n,		\
+		.ppxLogicOutputConfigArray = &Lcu_Ip_ppxLogicOutputArray##n##_Config[0],	\
+		.ppxLogicInputConfigArray = &Lcu_Ip_ppxLogicInputArray##n##_Config[0],		\
+	};
+
+#define Trgmux_Ip_LogicTrigger_Config(n, logic_channel, output, input)				\
+	{											\
+		.LogicChannel = logic_channel,							\
+		.Output = output,								\
+		.Input = input,									\
+		.HwInstId = TRGMUX_NXP_S32_GET_INSTANCE(DT_INST_PHANDLE(n, trgmux)),		\
+		.Lock = (boolean)FALSE,								\
+	};
+
+#define TRGMUX_IP_INIT_CONFIG(n)								\
+	const Trgmux_Ip_LogicTriggerType							\
+		Trgmux_Ip_LogicTrigger##n##_0_Config = Trgmux_Ip_LogicTrigger_Config(n,		\
+		DT_INST_PROP_BY_IDX(n, trgmux_io_config, 0),					\
+		DT_INST_PROP_BY_IDX(n, trgmux_io_config, 1),					\
+		DT_INST_PROP_BY_IDX(n, trgmux_io_config, 2))					\
+	const Trgmux_Ip_LogicTriggerType							\
+		Trgmux_Ip_LogicTrigger##n##_1_Config = Trgmux_Ip_LogicTrigger_Config(n,		\
+			DT_INST_PROP_BY_IDX(n, trgmux_io_config, 3),				\
+			DT_INST_PROP_BY_IDX(n, trgmux_io_config, 4),				\
+			DT_INST_PROP_BY_IDX(n, trgmux_io_config, 5))				\
+	const Trgmux_Ip_LogicTriggerType							\
+		Trgmux_Ip_LogicTrigger##n##_2_Config = Trgmux_Ip_LogicTrigger_Config(n,		\
+			DT_INST_PROP_BY_IDX(n, trgmux_io_config, 6),				\
+			DT_INST_PROP_BY_IDX(n, trgmux_io_config, 7),				\
+			DT_INST_PROP_BY_IDX(n, trgmux_io_config, 8))				\
+	const Trgmux_Ip_LogicTriggerType							\
+		Trgmux_Ip_LogicTrigger##n##_3_Config = Trgmux_Ip_LogicTrigger_Config(n,		\
+			DT_INST_PROP_BY_IDX(n, trgmux_io_config, 9),				\
+			DT_INST_PROP_BY_IDX(n, trgmux_io_config, 10),				\
+			DT_INST_PROP_BY_IDX(n, trgmux_io_config, 11))				\
+	const Trgmux_Ip_InitType Trgmux_Ip_Init_##n##_Config = {				\
+		.paxLogicTrigger = {								\
+			&Trgmux_Ip_LogicTrigger##n##_0_Config,					\
+			&Trgmux_Ip_LogicTrigger##n##_1_Config,					\
+			&Trgmux_Ip_LogicTrigger##n##_2_Config,					\
+			&Trgmux_Ip_LogicTrigger##n##_3_Config,					\
+		},										\
+	};
+
+
+#define QDEC_NXP_S32_INIT(n)									\
+												\
+	static struct qdec_s32_data qdec_s32_##n##_data = {					\
+		.micro_ticks_per_rev = (float)(DT_INST_PROP(n, micro_ticks_per_rev) / 1000000),	\
+		.counter_CW = 1,								\
+		.counter_CCW = 1,								\
+	};											\
+												\
+	PINCTRL_DT_INST_DEFINE(n);								\
+	TRGMUX_IP_INIT_CONFIG(n)								\
+	LCU_IP_INIT_CONFIG(n)									\
+	EMIOS_NXP_S32_MCB_OVERFLOW_CALLBACK(n)							\
+												\
+	static const struct qdec_s32_config qdec_s32_##n##_config = {				\
+		.emios_inst = EMIOS_NXP_S32_GET_INSTANCE(DT_INST_PHANDLE(n, emios)),		\
+		.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),					\
+		.trgmux_config = &Trgmux_Ip_Init_##n##_Config,					\
+		.lcu_config = &Lcu_Ip_Init_Config##n,						\
+		.emios_channels = {DT_INST_PROP_BY_IDX(n, emios_channels, EMIOS_CW_CH_IDX),	\
+				   DT_INST_PROP_BY_IDX(n, emios_channels, EMIOS_CCW_CH_IDX)},	\
+		.emios_cw_overflow_cb = &qdec##n##_emios_overflow_count_cw_callback,		\
+		.emios_ccw_overflow_cb = &qdec##n##_emios_overflow_count_ccw_callback,		\
+	};											\
+												\
+	SENSOR_DEVICE_DT_INST_DEFINE(n, qdec_s32_initialize, NULL, &qdec_s32_##n##_data,	\
+				     &qdec_s32_##n##_config, POST_KERNEL,			\
+				     CONFIG_SENSOR_INIT_PRIORITY, &qdec_s32_api);
+
+DT_INST_FOREACH_STATUS_OKAY(QDEC_NXP_S32_INIT)
diff --git a/dts/arm/nxp/nxp_s32k344_m7.dtsi b/dts/arm/nxp/nxp_s32k344_m7.dtsi
index 036b89a..0289b24 100644
--- a/dts/arm/nxp/nxp_s32k344_m7.dtsi
+++ b/dts/arm/nxp/nxp_s32k344_m7.dtsi
@@ -827,6 +827,24 @@
 				status = "disabled";
 			};
 		};
+
+		lcu0: lcu@40098000 {
+			compatible = "nxp,s32-lcu";
+			reg = <0x40098000 0x4000>;
+			status = "disabled";
+		};
+
+		lcu1: lcu@4009c000 {
+			compatible = "nxp,s32-lcu";
+			reg = <0x4009c000 0x4000>;
+			status = "disabled";
+		};
+
+		trgmux: trgmux@40080000 {
+			compatible = "nxp,s32-trgmux";
+			reg = <0x40080000 0x4000>;
+			status = "disabled";
+		};
 	};
 };
 
diff --git a/dts/bindings/misc/nxp,s32-lcu.yaml b/dts/bindings/misc/nxp,s32-lcu.yaml
new file mode 100644
index 0000000..51707de
--- /dev/null
+++ b/dts/bindings/misc/nxp,s32-lcu.yaml
@@ -0,0 +1,16 @@
+# Copyright 2023 NXP
+# SPDX-License-Identifier: Apache-2.0
+
+description: |
+  NXP S32 Logic control Unit node for S32 SoCs.
+  LCU selects multiple inputs from timers, Pulse Width Modulation
+  signals, and Input/Output (I/O) pads, and combines them
+  using a programmable logic function to create output waveforms
+
+compatible: "nxp,s32-lcu"
+
+include: [base.yaml]
+
+properties:
+  reg:
+    required: true
diff --git a/dts/bindings/misc/nxp,s32-trgmux.yaml b/dts/bindings/misc/nxp,s32-trgmux.yaml
new file mode 100644
index 0000000..55a589d
--- /dev/null
+++ b/dts/bindings/misc/nxp,s32-trgmux.yaml
@@ -0,0 +1,16 @@
+# Copyright 2023 NXP
+# SPDX-License-Identifier: Apache-2.0
+
+description: |
+  NXP S32 Trigger Multiplexing Control node for S32 SoCs.
+  The device supports the triggering scheme between peripherals.
+  The supported trigger sources and destination can be found in
+  the device Ref Manual
+
+compatible: "nxp,s32-trgmux"
+
+include: [base.yaml]
+
+properties:
+  reg:
+    required: true
diff --git a/dts/bindings/sensor/nxp,s32-qdec.yaml b/dts/bindings/sensor/nxp,s32-qdec.yaml
new file mode 100644
index 0000000..935d212
--- /dev/null
+++ b/dts/bindings/sensor/nxp,s32-qdec.yaml
@@ -0,0 +1,112 @@
+# Copyright 2023 NXP
+# SPDX-License-Identifier: Apache-2.0
+
+description: |
+  Quadrature Decoder driver which processes encoder signals to determine motor revs
+  with the cooperation of S32 IP blocks- eMIOS, TRGMUX and LCU.
+  The sensor qdec application can be used for testing this driver.
+  The following example uses TRGMUX IN2 and IN3 to connect to LCU1 LC0 I0 and I1.
+  LCU1 LC0 O2 and O3 connect to eMIOS0 CH6(Clockwise rotation) and
+  CH7(Counter Clockwise rotation) via TRGMUX_INT_OUT37 and TRGMUX_INT_OUT38
+  micro-ticks-per-rev is set as per vehicle gearbox reduction.
+  lcu output filters are set to capture maximum speed sensitivity and avoid channel noise.
+
+   qdec0 {
+        compatible = "nxp,qdec-s32";
+        pinctrl-0 = <&qdec_s32>;
+        pinctrl-names = "default";
+        micro-ticks-per-rev = <685440000>;
+        status = "okay";
+        trgmux = <&trgmux>;
+        trgmux-io-config =
+            <0 TRGMUX_IP_OUTPUT_EMIOS0_CH5_9_IPP_IND_CH6 TRGMUX_IP_INPUT_LCU1_LC0_OUT_I2>,
+            <1 TRGMUX_IP_OUTPUT_EMIOS0_CH5_9_IPP_IND_CH7 TRGMUX_IP_INPUT_LCU1_LC0_OUT_I3>,
+            <2 TRGMUX_IP_OUTPUT_LCU1_0_INP_I0            TRGMUX_IP_INPUT_SIUL2_IN2>,
+            <3 TRGMUX_IP_OUTPUT_LCU1_0_INP_I1            TRGMUX_IP_INPUT_SIUL2_IN3>;
+        lcu = <&lcu1>;
+        lcu-input-idx = <1>;
+            <LCU_IP_IN_0 LCU_IP_IN_1
+            LCU_IP_IN_2 LCU_IP_IN_3>;
+        lcu-mux-sel =
+            <LCU_IP_MUX_SEL_LU_IN_0 LCU_IP_MUX_SEL_LU_IN_1
+            LCU_IP_MUX_SEL_LU_OUT_0 LCU_IP_MUX_SEL_LU_OUT_1>;
+        lcu-output-filter-config =
+            /* LCU Out HW ID, Rise Filter, Fall Filter */
+            <0 5 5>, /* LCU O0 */
+            <1 5 5>, /* LCU O1 */
+            <2 2 2>, /* LCU O2 */
+            <3 2 2>; /* LCU O3 */
+        emios = <&emios0>;
+        emios-channels = <6 7>;
+   };
+
+compatible: "nxp,qdec-s32"
+
+include: [pinctrl-device.yaml, sensor-device.yaml]
+
+properties:
+  micro-ticks-per-rev:
+    type: int
+    description: |
+      This is a number that is used to determine how many revolutions * 1000000
+      were done based on the current counter's value.
+
+  trgmux:
+    type: phandle
+    description: |
+      phandle to the TRGMUX node.
+
+  trgmux-io-config:
+    type: array
+    description: |
+      This gives the logic triggers configuration of TRGMUX module.
+      It contains 3 values for each of the 4 logic triggers used:
+        logic trigger number, output, input.
+      Hence, it's length should be '12'.
+      Ex:
+        trgmux-io-config =
+          <0 TRGMUX_IP_OUTPUT_EMIOS0_CH5_9_IPP_IND_CH6 TRGMUX_IP_INPUT_LCU1_LC0_OUT_I2>,
+          <1 TRGMUX_IP_OUTPUT_EMIOS0_CH5_9_IPP_IND_CH7 TRGMUX_IP_INPUT_LCU1_LC0_OUT_I3>,
+          <2 TRGMUX_IP_OUTPUT_LCU1_0_INP_I0            TRGMUX_IP_INPUT_SIUL2_IN2>,
+          <3 TRGMUX_IP_OUTPUT_LCU1_0_INP_I1            TRGMUX_IP_INPUT_SIUL2_IN3>;
+
+  lcu:
+    type: phandle
+    description: |
+      phandle to the LCU node.
+
+  emios:
+    type: phandle
+    description: |
+      phandle to the eMIOS node.
+
+  lcu-output-filter-config:
+    type: array
+    description: |
+      This array gives the configuration for each of the four outputs of LCU module.
+      It contains the following for each output: hardware output id, rise filter and fall filter.
+      The filters specify the delay in terms of CORE_CLK between the input and output line of LC.
+        We use this delay to generate short pulses at the rising and falling edges of input pulse.
+      It's length should be '12' - 3 entries for each of the four LCU outputs.
+      Ex: lcu-output-filter-config =
+        /* LCU Out HW ID, Rise Filter, Fall Filter */
+        <0 5 5>, /* LCU O0 */
+        <1 5 5>, /* LCU O1 */
+        <2 2 2>, /* LCU O2 */
+        <3 2 2>; /* LCU O3 */
+
+  lcu-mux-sel:
+    type: array
+    description: |
+      This array configures the sources of input to the LCU module by programming the muxsel.
+
+  lcu-input-idx:
+    type: array
+    description: |
+      This array configures the input indices to the LCU module which help to determine the
+      Logic Cell number used inside an LCU instance.
+
+  emios-channels:
+    type: array
+    description: |
+      This is the array containing 2 emios channel TypeG numbers used by the qdec.
diff --git a/include/zephyr/dt-bindings/sensor/qdec_nxp_s32.h b/include/zephyr/dt-bindings/sensor/qdec_nxp_s32.h
new file mode 100644
index 0000000..c7df471
--- /dev/null
+++ b/include/zephyr/dt-bindings/sensor/qdec_nxp_s32.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2023 NXP
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* Logic Trigger Numbers. See Trgmux_Ip_Init_PBcfg.h */
+#define TRGMUX_LOGIC_GROUP_0_TRIGGER_0 (0) /* Logic Trigger 0 */
+#define TRGMUX_LOGIC_GROUP_0_TRIGGER_1 (1) /* Logic Trigger 1 */
+#define TRGMUX_LOGIC_GROUP_1_TRIGGER_0 (2) /* Logic Trigger 2 */
+#define TRGMUX_LOGIC_GROUP_1_TRIGGER_1 (3) /* Logic Trigger 3 */
+
+/*-----------------------------------------------
+ * TRGMUX HARDWARE TRIGGER INPUT
+ * See Trgmux_Ip_Cfg_Defines.h
+ *-----------------------------------------------
+ */
+#define TRGMUX_IP_INPUT_SIUL2_IN0  (60)
+#define TRGMUX_IP_INPUT_SIUL2_IN1  (61)
+#define TRGMUX_IP_INPUT_SIUL2_IN2  (62)
+#define TRGMUX_IP_INPUT_SIUL2_IN3  (63)
+#define TRGMUX_IP_INPUT_SIUL2_IN4  (64)
+#define TRGMUX_IP_INPUT_SIUL2_IN5  (65)
+#define TRGMUX_IP_INPUT_SIUL2_IN6  (66)
+#define TRGMUX_IP_INPUT_SIUL2_IN7  (67)
+#define TRGMUX_IP_INPUT_SIUL2_IN8  (68)
+#define TRGMUX_IP_INPUT_SIUL2_IN9  (69)
+#define TRGMUX_IP_INPUT_SIUL2_IN10 (70)
+#define TRGMUX_IP_INPUT_SIUL2_IN11 (71)
+#define TRGMUX_IP_INPUT_SIUL2_IN12 (72)
+#define TRGMUX_IP_INPUT_SIUL2_IN13 (73)
+#define TRGMUX_IP_INPUT_SIUL2_IN14 (74)
+#define TRGMUX_IP_INPUT_SIUL2_IN15 (75)
+
+#define TRGMUX_IP_INPUT_LCU1_LC0_OUT_I0 (105)
+#define TRGMUX_IP_INPUT_LCU1_LC0_OUT_I1 (106)
+#define TRGMUX_IP_INPUT_LCU1_LC0_OUT_I2 (107)
+#define TRGMUX_IP_INPUT_LCU1_LC0_OUT_I3 (108)
+
+/*-----------------------------------------------
+ *  TRGMUX HARDWARE TRIGGER OUTPUT
+ *  See Trgmux_Ip_Cfg_Defines.h
+ *-----------------------------------------------
+ */
+#define TRGMUX_IP_OUTPUT_LCU1_0_INP_I0 (144)
+#define TRGMUX_IP_OUTPUT_LCU1_0_INP_I1 (145)
+#define TRGMUX_IP_OUTPUT_LCU1_0_INP_I2 (146)
+#define TRGMUX_IP_OUTPUT_LCU1_0_INP_I3 (147)
+
+#define TRGMUX_IP_OUTPUT_EMIOS0_CH1_4_IPP_IND_CH1    (32)
+#define TRGMUX_IP_OUTPUT_EMIOS0_CH1_4_IPP_IND_CH2    (33)
+#define TRGMUX_IP_OUTPUT_EMIOS0_CH1_4_IPP_IND_CH3    (34)
+#define TRGMUX_IP_OUTPUT_EMIOS0_CH1_4_IPP_IND_CH4    (35)
+#define TRGMUX_IP_OUTPUT_EMIOS0_CH5_9_IPP_IND_CH5    (36)
+#define TRGMUX_IP_OUTPUT_EMIOS0_CH5_9_IPP_IND_CH6    (37)
+#define TRGMUX_IP_OUTPUT_EMIOS0_CH5_9_IPP_IND_CH7    (38)
+#define TRGMUX_IP_OUTPUT_EMIOS0_CH5_9_IPP_IND_CH9    (39)
+#define TRGMUX_IP_OUTPUT_EMIOS0_CH10_13_IPP_IND_CH10 (40)
+#define TRGMUX_IP_OUTPUT_EMIOS0_CH10_13_IPP_IND_CH11 (41)
+#define TRGMUX_IP_OUTPUT_EMIOS0_CH10_13_IPP_IND_CH12 (42)
+#define TRGMUX_IP_OUTPUT_EMIOS0_CH10_13_IPP_IND_CH13 (43)
+#define TRGMUX_IP_OUTPUT_EMIOS0_CH14_15_IPP_IND_CH14 (44)
+#define TRGMUX_IP_OUTPUT_EMIOS0_CH14_15_IPP_IND_CH15 (45)
+
+/*-----------------------------------------------
+ *  LCU SOURCE MUX SELECT
+ *  See Lcu_Ip_Cfg_Defines.h
+ *-----------------------------------------------
+ */
+#define LCU_IP_MUX_SEL_LOGIC_0                   (0)
+#define LCU_IP_MUX_SEL_LU_IN_0                   (1)
+#define LCU_IP_MUX_SEL_LU_IN_1                   (2)
+#define LCU_IP_MUX_SEL_LU_IN_2                   (3)
+#define LCU_IP_MUX_SEL_LU_IN_3                   (4)
+#define LCU_IP_MUX_SEL_LU_IN_4                   (5)
+#define LCU_IP_MUX_SEL_LU_IN_5                   (6)
+#define LCU_IP_MUX_SEL_LU_IN_6                   (7)
+#define LCU_IP_MUX_SEL_LU_IN_7                   (8)
+#define LCU_IP_MUX_SEL_LU_IN_8                   (9)
+#define LCU_IP_MUX_SEL_LU_IN_9                   (10)
+#define LCU_IP_MUX_SEL_LU_IN_10                  (11)
+#define LCU_IP_MUX_SEL_LU_IN_11                  (12)
+#define LCU_IP_MUX_SEL_LU_OUT_0                  (13)
+#define LCU_IP_MUX_SEL_LU_OUT_1                  (14)
+#define LCU_IP_MUX_SEL_LU_OUT_2                  (15)
+#define LCU_IP_MUX_SEL_LU_OUT_3                  (16)
+#define LCU_IP_MUX_SEL_LU_OUT_4                  (17)
+#define LCU_IP_MUX_SEL_LU_OUT_5                  (18)
+#define LCU_IP_MUX_SEL_LU_OUT_6                  (19)
+#define LCU_IP_MUX_SEL_LU_OUT_7                  (20)
+#define LCU_IP_MUX_SEL_LU_OUT_8                  (21)
+#define LCU_IP_MUX_SEL_LU_OUT_9                  (22)
+#define LCU_IP_MUX_SEL_LU_OUT_10                 (23)
+#define LCU_IP_MUX_SEL_LU_OUT_11                 (24)
+
+#define LCU_IP_IN_0				 (0)
+#define LCU_IP_IN_1				 (1)
+#define LCU_IP_IN_2				 (2)
+#define LCU_IP_IN_3				 (3)
+#define LCU_IP_IN_4				 (4)
+#define LCU_IP_IN_5				 (5)
+#define LCU_IP_IN_6				 (6)
+#define LCU_IP_IN_7				 (7)
+#define LCU_IP_IN_8				 (8)
+#define LCU_IP_IN_9				 (9)
+#define LCU_IP_IN_10				 (10)
+#define LCU_IP_IN_11				 (11)