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

drivers: dac: Introduce gd32 driver #41152

Merged
merged 4 commits into from
Dec 16, 2021
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions boards/arm/gd32f450i_eval/doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ The board configuration supports the following hardware features:
* - USART
- :kconfig:`CONFIG_SERIAL`
- :dtcompatible:`gd,gd32-usart`
* - DAC
- :kconfig:`CONFIG_DAC`
- :dtcompatible:`gd,gd32-dac`

Serial Port
===========
Expand Down
6 changes: 6 additions & 0 deletions boards/arm/gd32f450i_eval/gd32f450i_eval-pinctrl.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,10 @@
pinmux = <USART0_TX_PA9>, <USART0_RX_PA10>;
};
};

dac_default: dac_default {
group1 {
pinmux = <DAC_OUT0_PA4>;
};
};
};
6 changes: 6 additions & 0 deletions boards/arm/gd32f450i_eval/gd32f450i_eval.dts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,9 @@
pinctrl-0 = <&usart0_default>;
pinctrl-names = "default";
};

&dac {
status = "okay";
pinctrl-0 = <&dac_default>;
pinctrl-names = "default";
};
1 change: 1 addition & 0 deletions drivers/dac/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ zephyr_library_sources_ifdef(CONFIG_DAC_DACX0508 dac_dacx0508.c)
zephyr_library_sources_ifdef(CONFIG_DAC_DACX3608 dac_dacx3608.c)
zephyr_library_sources_ifdef(CONFIG_DAC_SHELL dac_shell.c)
zephyr_library_sources_ifdef(CONFIG_DAC_MCP4725 dac_mcp4725.c)
zephyr_library_sources_ifdef(CONFIG_DAC_GD32 dac_gd32.c)
zephyr_library_sources_ifdef(CONFIG_USERSPACE dac_handlers.c)
2 changes: 2 additions & 0 deletions drivers/dac/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,6 @@ source "drivers/dac/Kconfig.dacx3608"

source "drivers/dac/Kconfig.mcp4725"

source "drivers/dac/Kconfig.gd32"

endif # DAC
15 changes: 15 additions & 0 deletions drivers/dac/Kconfig.gd32
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# DAC configuration options

# Copyright (c) 2021 BrainCo Inc.
#
# SPDX-License-Identifier: Apache-2.0

# Workaround for not being able to have commas in macro arguments
DT_COMPAT_GD_GD32_DAC := gd,gd32-dac

config DAC_GD32
bool "GD32 DAC driver"
depends on SOC_FAMILY_GD32
default $(dt_compat_enabled,$(DT_COMPAT_GD_GD32_DAC))
help
Enable GigaDevice GD32 DAC driver
167 changes: 167 additions & 0 deletions drivers/dac/dac_gd32.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/*
* Copyright (c) 2021 BrainCo Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT gd_gd32_dac

#include <errno.h>
#include <drivers/pinctrl.h>
#include <drivers/dac.h>
#include <soc.h>

#include <logging/log.h>
LOG_MODULE_REGISTER(dac_gd32, CONFIG_DAC_LOG_LEVEL);

/**
* GD32 DAC HAL use different DAC0 interface for 2 or 1 output channels SoCs.
* Unify the DAC0 interface to DAC0_xx.
*/
#if DT_INST_PROP(0, num_channels) == 1
#define DAC_CTL_DEN0 DAC_CTL_DEN
#define DAC0_R8DH DAC_R8DH
#define DAC0_R12DH DAC_R12DH
#endif

struct dac_gd32_config {
uint32_t reg;
uint32_t rcu_periph_clock;
const struct pinctrl_dev_config *pcfg;
uint32_t num_channels;
uint32_t reset_val;
};

struct dac_gd32_data {
uint8_t resolutions[2];
};

static void dac_gd32_enable(uint8_t dacx)
{
switch (dacx) {
case 0U:
DAC_CTL |= DAC_CTL_DEN0;
break;
#if DT_INST_PROP(0, num_channels) == 2
case 1U:
DAC_CTL |= DAC_CTL_DEN1;
break;
#endif
}
}

static void dac_gd32_disable(uint8_t dacx)
{
switch (dacx) {
case 0U:
DAC_CTL &= ~DAC_CTL_DEN0;
break;
#if DT_INST_PROP(0, num_channels) == 2
case 1U:
DAC_CTL &= ~DAC_CTL_DEN1;
break;
#endif
}
}

static void dac_gd32_write(struct dac_gd32_data *data,
uint8_t dacx, uint32_t value)
{
switch (dacx) {
case 0U:
if (data->resolutions[dacx] == 8U) {
DAC0_R8DH = value;
} else {
DAC0_R12DH = value;
}
break;
#if DT_INST_PROP(0, num_channels) == 2
case 1U:
if (data->resolutions[dacx] == 8U) {
DAC1_R8DH = value;
} else {
DAC1_R12DH = value;
}
break;
#endif
}
}

static int dac_gd32_channel_setup(const struct device *dev,
const struct dac_channel_cfg *channel_cfg)
{
struct dac_gd32_data *data = dev->data;
const struct dac_gd32_config *config = dev->config;
uint8_t dacx = channel_cfg->channel_id;

if (dacx >= config->num_channels) {
return -ENOTSUP;
}

/* GD32 DAC only support 8 or 12 bits resolution */
if ((channel_cfg->resolution != 8U) &&
(channel_cfg->resolution != 12U)) {
LOG_ERR("Only 8 and 12 bits resolutions are supported!");
return -ENOTSUP;
}

data->resolutions[dacx] = channel_cfg->resolution;

dac_gd32_disable(dacx);
dac_gd32_write(data, dacx, config->reset_val);
dac_gd32_enable(dacx);

return 0;
}

static int dac_gd32_write_value(const struct device *dev,
uint8_t dacx, uint32_t value)
{
struct dac_gd32_data *data = dev->data;
const struct dac_gd32_config *config = dev->config;

if (dacx >= config->num_channels) {
return -ENOTSUP;
}

dac_gd32_write(data, dacx, value);

return 0;
}

struct dac_driver_api dac_gd32_driver_api = {
.channel_setup = dac_gd32_channel_setup,
.write_value = dac_gd32_write_value
};

static int dac_gd32_init(const struct device *dev)
{
const struct dac_gd32_config *cfg = dev->config;
int ret;

ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
if (ret < 0) {
LOG_ERR("Failed to apply pinctrl state");
return ret;
}

rcu_periph_clock_enable(cfg->rcu_periph_clock);

return 0;
}

PINCTRL_DT_INST_DEFINE(0)

static struct dac_gd32_data dac_gd32_data_0;

static const struct dac_gd32_config dac_gd32_cfg_0 = {
.reg = DT_INST_REG_ADDR(0),
.rcu_periph_clock = DT_INST_PROP(0, rcu_periph_clock),
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0),
.num_channels = DT_INST_PROP(0, num_channels),
.reset_val = DT_INST_PROP(0, reset_val),
};

DEVICE_DT_INST_DEFINE(0, &dac_gd32_init, NULL, &dac_gd32_data_0,
&dac_gd32_cfg_0, POST_KERNEL, CONFIG_DAC_INIT_PRIORITY,
&dac_gd32_driver_api);
22 changes: 22 additions & 0 deletions dts/arm/gigadevice/gd32f3x0/gd32f350.dtsi
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2021 BrainCo Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <mem.h>
#include <gigadevice/gd32f3x0/gd32f3x0.dtsi>

/ {
soc {
dac: dac@40007400 {
compatible = "gd,gd32-dac";
reg = <0x40007400 0x400>;
rcu-periph-clock = <0x71d>;
num-channels = <1>;
label = "DAC";
status = "disabled";
#io-channel-cells = <1>;
};
};
};
2 changes: 1 addition & 1 deletion dts/arm/gigadevice/gd32f3x0/gd32f350g6.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

#include <mem.h>
#include <gigadevice/gd32f3x0/gd32f3x0.dtsi>
#include <gigadevice/gd32f3x0/gd32f350.dtsi>

/ {
soc {
Expand Down
2 changes: 1 addition & 1 deletion dts/arm/gigadevice/gd32f3x0/gd32f350rb.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

#include <mem.h>
#include <gigadevice/gd32f3x0/gd32f3x0.dtsi>
#include <gigadevice/gd32f3x0/gd32f350.dtsi>

/ {
soc {
Expand Down
10 changes: 10 additions & 0 deletions dts/arm/gigadevice/gd32f4xx/gd32f4xx.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,16 @@
label = "USART_7";
};

dac: dac@40007400 {
compatible = "gd,gd32-dac";
reg = <0x40007400 0x400>;
rcu-periph-clock = <0x101d>;
num-channels = <2>;
label = "DAC";
status = "disabled";
#io-channel-cells = <1>;
};

pinctrl: pin-controller@40020000 {
compatible = "gd,gd32-pinctrl-af";
reg = <0x40020000 0x2400>;
Expand Down
34 changes: 34 additions & 0 deletions dts/bindings/dac/gd,gd32-dac.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright (c) 2021 BrainCo Inc.
# SPDX-License-Identifier: Apache-2.0

description: GigaDevice GD32 series DAC module

compatible: "gd,gd32-dac"

include: [dac-controller.yaml, pinctrl-device.yaml]

properties:
reg:
required: true

rcu-periph-clock:
type: int
description: Reset Control Unit Peripheral Clock ID
required: true

num-channels:
type: int
description: Number of DAC output channels
required: true

reset-val:
type: int
default: 0
description: Reset value of DAC output. Defaults to 0, the SoC default.
required: false

"#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 @@ -176,6 +176,19 @@ built and executed for the :ref:`bl5340_dvk` as follows:

DAC output is available on pin 1 of the MCP4725.

Building and Running for GD32450I-EVAL
======================================
The sample can be built and executed for the
:ref:`gd32f450i_eval` as follows:

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

Bridge the JP23 to DAC with the jumper cap, then DAC output will available on JP7.

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

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

/ {
zephyr,user {
dac = <&dac>;
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 @@ -7,6 +7,7 @@ tests:
arduino_zero frdm_k22f frdm_k64f nucleo_f091rc nucleo_g071rb nucleo_g431rb
nucleo_l073rz nucleo_l152re twr_ke18f nucleo_f767zi nucleo_f429zi bl652_dvk
bl653_dvk bl654_dvk bl5340_dvk_cpuapp stm32f3_disco stm32l562e_dk nucleo_l552ze_q
gd32f450i_eval
depends_on: dac
harness: console
harness_config:
Expand Down