Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable lpdac for lpcxpresso55s36 #61459

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions boards/arm/lpcxpresso55s36/doc/index.rst
martinjaeger marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ already supported, which can also be re-used on this lpcxpresso55s36 board:
+-----------+------------+-------------------------------------+
| USB FS | on-chip | USB Full Speed device |
+-----------+------------+-------------------------------------+
| DAC | on-chip | dac |
+-----------+------------+-------------------------------------+
martinjaeger marked this conversation as resolved.
Show resolved Hide resolved

Other hardware features are not currently enabled.

Expand Down
10 changes: 9 additions & 1 deletion boards/arm/lpcxpresso55s36/lpcxpresso55s36-pinctrl.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* NOTE: File generated by lpc_cfg_utils.py
* from LPC55S36.mex
*
* Copyright 2022 NXP
* Copyright 2022-2023 NXP
Albort12138 marked this conversation as resolved.
Show resolved Hide resolved
* SPDX-License-Identifier: Apache-2.0
*/

Expand Down Expand Up @@ -119,4 +119,12 @@
slew-rate = "standard";
};
};

pinmux_dac0: pinmux_dac0 {
group0 {
pinmux = <DAC0_OUT_PIO1_22>;
slew-rate = "standard";
nxp,analog-mode;
};
};
};
6 changes: 6 additions & 0 deletions boards/arm/lpcxpresso55s36/lpcxpresso55s36.dts
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,9 @@ zephyr_udc0: &usbfs {
&dma0 {
status = "okay";
};

&dac0 {
martinjaeger marked this conversation as resolved.
Show resolved Hide resolved
status = "okay";
pinctrl-0 = <&pinmux_dac0>;
pinctrl-names = "default";
};
1 change: 1 addition & 0 deletions boards/arm/lpcxpresso55s36/lpcxpresso55s36.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ supported:
- can
- gpio
- pwm
- dac
1 change: 1 addition & 0 deletions drivers/dac/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/dac.h)

zephyr_library()

zephyr_library_sources_ifdef(CONFIG_DAC_MCUX_LPDAC dac_mcux_lpdac.c)
zephyr_library_sources_ifdef(CONFIG_DAC_MCUX_DAC dac_mcux_dac.c)
zephyr_library_sources_ifdef(CONFIG_DAC_MCUX_DAC32 dac_mcux_dac32.c)
zephyr_library_sources_ifdef(CONFIG_DAC_STM32 dac_stm32.c)
Expand Down
7 changes: 7 additions & 0 deletions drivers/dac/Kconfig.mcux
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ config DAC_MCUX_DAC32
help
Enable the driver for the NXP Kinetis MCUX DAC32.

config DAC_MCUX_LPDAC
bool "NXP MCUX LPDAC driver"
default y
depends on DT_HAS_NXP_LPDAC_ENABLED
help
Enable the driver for the NXP MCUX LPDAC.

config DAC_MCUX_DAC32_TESTOUT
bool "DAC test output"
depends on DAC_MCUX_DAC32
Expand Down
107 changes: 107 additions & 0 deletions drivers/dac/dac_mcux_lpdac.c
martinjaeger marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright (c) 2020 Henrik Brix Andersen <henrik@brixandersen.dk>
martinjaeger marked this conversation as resolved.
Show resolved Hide resolved
* Copyright (c) 2023, NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT nxp_lpdac

#include <zephyr/kernel.h>
#include <zephyr/drivers/dac.h>
#include <zephyr/logging/log.h>

#include <fsl_dac.h>

LOG_MODULE_REGISTER(dac_mcux_lpdac, CONFIG_DAC_LOG_LEVEL);

struct mcux_lpdac_config {
LPDAC_Type *base;
dac_reference_voltage_source_t ref_voltage;
bool low_power;
};

struct mcux_lpdac_data {
bool configured;
};

static int mcux_lpdac_channel_setup(const struct device *dev,
const struct dac_channel_cfg *channel_cfg)
{
const struct mcux_lpdac_config *config = dev->config;
struct mcux_lpdac_data *data = dev->data;
dac_config_t dac_config;

if (channel_cfg->channel_id != 0) {
LOG_ERR("unsupported channel %d", channel_cfg->channel_id);
return -ENOTSUP;
}

if (channel_cfg->resolution != 12) {
LOG_ERR("unsupported resolution %d", channel_cfg->resolution);
return -ENOTSUP;
}

DAC_GetDefaultConfig(&dac_config);
dac_config.referenceVoltageSource = config->ref_voltage;
#if defined(FSL_FEATURE_LPDAC_HAS_GCR_BUF_SPD_CTRL) && FSL_FEATURE_LPDAC_HAS_GCR_BUF_SPD_CTRL
dac_config.enableLowerLowPowerMode = config->low_power;
#else
dac_config.enableLowPowerMode = config->low_power;
#endif
DAC_Init(config->base, &dac_config);
DAC_Enable(config->base, false);
data->configured = true;

return 0;
}

static int mcux_lpdac_write_value(const struct device *dev, uint8_t channel, uint32_t value)
{
const struct mcux_lpdac_config *config = dev->config;
struct mcux_lpdac_data *data = dev->data;

if (!data->configured) {
LOG_ERR("channel not initialized");
return -EINVAL;
}

if (channel != 0) {
LOG_ERR("unsupported channel %d", channel);
return -ENOTSUP;
}

if (value >= 4096) {
LOG_ERR("unsupported value %d", value);
return -EINVAL;
}

DAC_Enable(config->base, true);
DAC_SetData(config->base, value);

return 0;
}

static int mcux_lpdac_init(const struct device *dev)
{
return 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we call DAC_Init() from this function instead of channel_setup? The init should be done only once.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DAC_Init is the only function that the SDK provides to configure the channels, so I don't think so.

}

static const struct dac_driver_api mcux_lpdac_driver_api = {
.channel_setup = mcux_lpdac_channel_setup,
.write_value = mcux_lpdac_write_value,
};

#define MCUX_LPDAC_INIT(n) \
static struct mcux_lpdac_data mcux_lpdac_data_##n; \
\
static const struct mcux_lpdac_config mcux_lpdac_config_##n = { \
.base = (LPDAC_Type *)DT_INST_REG_ADDR(n), \
.ref_voltage = DT_INST_PROP(n, voltage_reference), \
.low_power = DT_INST_PROP(n, low_power_mode), \
}; \
\
DEVICE_DT_INST_DEFINE(n, mcux_lpdac_init, NULL, &mcux_lpdac_data_##n, \
&mcux_lpdac_config_##n, POST_KERNEL, CONFIG_DAC_INIT_PRIORITY, \
&mcux_lpdac_driver_api);

DT_INST_FOREACH_STATUS_OKAY(MCUX_LPDAC_INIT)
27 changes: 27 additions & 0 deletions dts/arm/nxp/nxp_lpc55S3x_common.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,33 @@
dma-names = "adc0-dma0", "adc0-dma1";
};

dac0: dac@b2000 {
compatible = "nxp,lpdac";
reg = < 0xb2000 0x1000>;
interrupts = <74 0>;
status = "disabled";
voltage-reference = <0>;
#io-channel-cells = <1>;
};

dac1: dac@b6000 {
compatible = "nxp,lpdac";
reg = < 0xb6000 0x1000>;
interrupts = <75 0>;
status = "disabled";
voltage-reference = <0>;
#io-channel-cells = <1>;
};

dac2: dac@b9000 {
compatible = "nxp,lpdac";
reg = < 0xb9000 0x1000>;
interrupts = <76 0>;
status = "disabled";
voltage-reference = <0>;
#io-channel-cells = <1>;
};

can0: can@4009d000 {
compatible = "nxp,lpc-mcan";
reg = <0x4009d000 0x1000>;
Expand Down
29 changes: 29 additions & 0 deletions dts/bindings/dac/nxp,lpdac.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Copyright (c) 2023, NXP
# SPDX-License-Identifier: Apache-2.0

description: NXP MCUX LPDAC

compatible: "nxp,lpdac"

include: dac-controller.yaml

properties:
reg:
required: true

voltage-reference:
type: int
required: true
description: |
DAC voltage reference select. The meaning of the value may be
different for different SoCs.

low-power-mode:
type: boolean
description: Enable low-power mode

"#io-channel-cells":
const: 1

io-channel-cells:
- output
13 changes: 13 additions & 0 deletions samples/drivers/dac/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,19 @@ also can run for the
:goals: build flash
:compact:

Building and Running for NXP LPCXpresso55S36
============================================
The sample can be built and executed for the :ref:`lpcxpresso55s36` as
follows:

.. zephyr-app-commands::
:zephyr-app: samples/drivers/dac
:board: lpcxpresso55s36
:goals: build flash
:compact:

DAC output is available on connector J12 pin 4.
martinjaeger marked this conversation as resolved.
Show resolved Hide resolved

Sample output
=============

Expand Down
13 changes: 13 additions & 0 deletions samples/drivers/dac/boards/lpcxpresso55s36.overlay
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright 2023 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/

/ {
martinjaeger marked this conversation as resolved.
Show resolved Hide resolved
zephyr,user {
dac = <&dac0>;
dac-channel-id = <0>;
dac-resolution = <12>;
};
};
1 change: 1 addition & 0 deletions samples/drivers/dac/sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ tests:
- stm32f3_disco
- stm32l562e_dk
- twr_ke18f
- lpcxpresso55s36
depends_on: dac
integration_platforms:
- nucleo_l152re
Expand Down
31 changes: 21 additions & 10 deletions soc/arm/nxp_lpc/lpc55xxx/soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
#include "usb_phy.h"
#include "usb.h"
#endif
#if defined(CONFIG_SOC_LPC55S36) && defined(CONFIG_ADC_MCUX_LPADC)
#if defined(CONFIG_SOC_LPC55S36) && (defined(CONFIG_ADC_MCUX_LPADC) \
|| defined(CONFIG_DAC_MCUX_LPDAC))
#include <fsl_vref.h>
#endif

Expand Down Expand Up @@ -322,8 +323,26 @@ DT_FOREACH_STATUS_OKAY(nxp_lpc_ctimer, CTIMER_CLOCK_SETUP)
#if defined(CONFIG_SOC_LPC55S36)
CLOCK_SetClkDiv(kCLOCK_DivAdc0Clk, 2U, true);
CLOCK_AttachClk(kFRO_HF_to_ADC0);
#else
CLOCK_SetClkDiv(kCLOCK_DivAdcAsyncClk,
DT_PROP(DT_NODELABEL(adc0), clk_divider), true);
CLOCK_AttachClk(MUX_A(CM_ADCASYNCCLKSEL, DT_PROP(DT_NODELABEL(adc0), clk_source)));

#if defined(CONFIG_ADC_MCUX_LPADC)
/* Power up the ADC */
POWER_DisablePD(kPDRUNCFG_PD_LDOGPADC);
#endif
#endif
#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(dac0), nxp_lpdac, okay)
#if defined(CONFIG_SOC_LPC55S36)
Albort12138 marked this conversation as resolved.
Show resolved Hide resolved
CLOCK_SetClkDiv(kCLOCK_DivDac0Clk, 1U, true);
CLOCK_AttachClk(kMAIN_CLK_to_DAC0);

/* Disable DAC0 power down */
POWER_DisablePD(kPDRUNCFG_PD_DAC0);
#endif
#endif
#if defined(CONFIG_SOC_LPC55S36)
#if (defined(CONFIG_ADC_MCUX_LPADC) || defined(CONFIG_DAC_MCUX_LPDAC))
/* Vref is required for LPADC reference */
POWER_DisablePD(kPDRUNCFG_PD_VREF);

Expand All @@ -335,14 +354,6 @@ DT_FOREACH_STATUS_OKAY(nxp_lpc_ctimer, CTIMER_CLOCK_SETUP)
vrefConfig.enableVrefOut = true;
VREF_Init((VREF_Type *)VREF_BASE, &vrefConfig);
#endif
#else
CLOCK_SetClkDiv(kCLOCK_DivAdcAsyncClk,
DT_PROP(DT_NODELABEL(adc0), clk_divider), true);
CLOCK_AttachClk(MUX_A(CM_ADCASYNCCLKSEL, DT_PROP(DT_NODELABEL(adc0), clk_source)));

/* Power up the ADC */
POWER_DisablePD(kPDRUNCFG_PD_LDOGPADC);
#endif
#endif
}

Expand Down
3 changes: 2 additions & 1 deletion tests/drivers/dac/dac_api/src/test_dac.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
defined(CONFIG_BOARD_FRDM_K22F) || \
defined(CONFIG_BOARD_SEEEDUINO_XIAO) || \
defined(CONFIG_BOARD_ARDUINO_MKRZERO) || \
defined(CONFIG_BOARD_ARDUINO_ZERO)
defined(CONFIG_BOARD_ARDUINO_ZERO) || \
defined(CONFIG_BOARD_LPCXPRESSO55S36)

#define DAC_DEVICE_NODE DT_NODELABEL(dac0)
#define DAC_RESOLUTION 12
Expand Down
10 changes: 10 additions & 0 deletions tests/drivers/dac/dac_loopback/boards/lpcxpresso55s36.overlay
martinjaeger marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright 2023 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/

&dac0 {
martinjaeger marked this conversation as resolved.
Show resolved Hide resolved
/* To align reference voltage with ADC. */
voltage-reference = <1>;
};
19 changes: 18 additions & 1 deletion tests/drivers/dac/dac_loopback/src/test_dac.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,22 @@
#define ADC_ACQUISITION_TIME ADC_ACQ_TIME_DEFAULT
#define ADC_CHANNEL_ID 23

#elif defined(CONFIG_BOARD_LPCXPRESSO55S36)

/* DAC0 output is internally available on ADC0_SE4 */

#define DAC_DEVICE_NODE DT_NODELABEL(dac0)
#define DAC_RESOLUTION 12
#define DAC_CHANNEL_ID 0

#define ADC_DEVICE_NODE DT_NODELABEL(adc0)
#define ADC_RESOLUTION 12
#define ADC_GAIN ADC_GAIN_1
#define ADC_REFERENCE ADC_REF_EXTERNAL0
#define ADC_ACQUISITION_TIME ADC_ACQ_TIME_DEFAULT
#define ADC_CHANNEL_ID 0
#define ADC_1ST_CHANNEL_INPUT 4

#elif defined(CONFIG_BOARD_BL652_DVK) || \
defined(CONFIG_BOARD_BL653_DVK) || \
defined(CONFIG_BOARD_BL654_DVK) || \
Expand Down Expand Up @@ -168,7 +184,8 @@ static const struct adc_channel_cfg adc_ch_cfg = {
#if defined(CONFIG_BOARD_BL652_DVK) || \
defined(CONFIG_BOARD_BL653_DVK) || \
defined(CONFIG_BOARD_BL654_DVK) || \
defined(CONFIG_BOARD_BL5340_DVK_CPUAPP)
defined(CONFIG_BOARD_BL5340_DVK_CPUAPP) || \
defined(CONFIG_BOARD_LPCXPRESSO55S36)
.input_positive = ADC_1ST_CHANNEL_INPUT,
#endif
};
Expand Down
1 change: 1 addition & 0 deletions tests/drivers/dac/dac_loopback/testcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@ tests:
- nucleo_f746zg
- nucleo_g071rb
- nucleo_wl55jc
- lpcxpresso55s36
integration_platforms:
- nucleo_f207zg