drivers: spi: support for Nuvoton numaker series
Add Nuvoton numaker series spi controller, including full and half duplex support. Signed-off-by: cyliang tw <cyliang@nuvoton.com>
This commit is contained in:
parent
207e5c77d4
commit
5148c98e83
6 changed files with 510 additions and 0 deletions
|
@ -40,6 +40,7 @@ zephyr_library_sources_ifdef(CONFIG_SPI_XMC4XXX spi_xmc4xxx.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_SPI_PW spi_pw.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SPI_SMARTBOND spi_smartbond.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SPI_OPENTITAN spi_opentitan.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SPI_NUMAKER spi_numaker.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_SPI_RTIO spi_rtio.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SPI_ASYNC spi_signal.c)
|
||||
|
|
|
@ -127,4 +127,6 @@ source "drivers/spi/Kconfig.smartbond"
|
|||
|
||||
source "drivers/spi/Kconfig.opentitan"
|
||||
|
||||
source "drivers/spi/Kconfig.numaker"
|
||||
|
||||
endif # SPI
|
||||
|
|
14
drivers/spi/Kconfig.numaker
Normal file
14
drivers/spi/Kconfig.numaker
Normal file
|
@ -0,0 +1,14 @@
|
|||
# NUMAKER SPI Driver configuration options
|
||||
|
||||
# Copyright (c) 2023 Nuvoton Technology Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config SPI_NUMAKER
|
||||
bool "Nuvoton NuMaker MCU SPI driver"
|
||||
default y
|
||||
select HAS_NUMAKER_SPI
|
||||
depends on DT_HAS_NUVOTON_NUMAKER_SPI_ENABLED
|
||||
help
|
||||
This option enables the SPI driver for Nuvoton NuMaker family of
|
||||
processors.
|
||||
Say y if you wish to enable NuMaker SPI.
|
351
drivers/spi/spi_numaker.c
Normal file
351
drivers/spi/spi_numaker.c
Normal file
|
@ -0,0 +1,351 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Copyright (c) 2023 Nuvoton Technology Corporation.
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT nuvoton_numaker_spi
|
||||
|
||||
#include <errno.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/reset.h>
|
||||
#include <zephyr/drivers/clock_control.h>
|
||||
#include <zephyr/drivers/clock_control/clock_control_numaker.h>
|
||||
#include <zephyr/drivers/pinctrl.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
LOG_MODULE_REGISTER(spi_numaker, CONFIG_SPI_LOG_LEVEL);
|
||||
|
||||
#include "spi_context.h"
|
||||
#include <NuMicro.h>
|
||||
|
||||
#define SPI_NUMAKER_TX_NOP 0x00
|
||||
|
||||
struct spi_numaker_config {
|
||||
SPI_T *spi;
|
||||
bool is_qspi;
|
||||
const struct reset_dt_spec reset;
|
||||
/* clock configuration */
|
||||
uint32_t clk_modidx;
|
||||
uint32_t clk_src;
|
||||
uint32_t clk_div;
|
||||
const struct device *clk_dev;
|
||||
const struct pinctrl_dev_config *pincfg;
|
||||
};
|
||||
|
||||
struct spi_numaker_data {
|
||||
struct spi_context ctx;
|
||||
};
|
||||
|
||||
/*
|
||||
* CPOL/CPHA = 0/0 --> SPI_MODE_0
|
||||
* CPOL/CPHA = 0/1 --> SPI_MODE_1
|
||||
* CPOL/CPHA = 1/0 --> SPI_MODE_2
|
||||
* CPOL/CPHA = 1/1 --> SPI_MODE_3
|
||||
*/
|
||||
static const uint32_t smode_tbl[4] = {
|
||||
SPI_MODE_0, SPI_MODE_1, SPI_MODE_2, SPI_MODE_3
|
||||
};
|
||||
|
||||
static const uint32_t qsmode_tbl[4] = {
|
||||
QSPI_MODE_0, QSPI_MODE_1, QSPI_MODE_2, QSPI_MODE_3
|
||||
};
|
||||
|
||||
static int spi_numaker_configure(const struct device *dev, const struct spi_config *config)
|
||||
{
|
||||
int mode;
|
||||
struct spi_numaker_data *data = dev->data;
|
||||
const struct spi_numaker_config *dev_cfg = dev->config;
|
||||
|
||||
LOG_DBG("%s", __func__);
|
||||
if (spi_context_configured(&data->ctx, config)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (SPI_MODE_GET(config->operation) & SPI_MODE_LOOP) {
|
||||
LOG_ERR("Loop back mode not support");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (SPI_OP_MODE_GET(config->operation) == SPI_OP_MODE_SLAVE) {
|
||||
LOG_ERR("Slave mode not support");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Clear FIFO */
|
||||
SPI_ClearRxFIFO(dev_cfg->spi);
|
||||
SPI_ClearTxFIFO(dev_cfg->spi);
|
||||
|
||||
if (SPI_MODE_GET(config->operation) & SPI_MODE_CPOL) {
|
||||
mode = (SPI_MODE_GET(config->operation) & SPI_MODE_CPHA) ? 3 : 2;
|
||||
} else {
|
||||
mode = (SPI_MODE_GET(config->operation) & SPI_MODE_CPHA) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Make SPI module be ready to transfer */
|
||||
if (dev_cfg->is_qspi) {
|
||||
QSPI_Open((QSPI_T *)dev_cfg->spi,
|
||||
(SPI_OP_MODE_GET(config->operation) == SPI_OP_MODE_SLAVE) ? QSPI_SLAVE
|
||||
: QSPI_MASTER,
|
||||
qsmode_tbl[mode],
|
||||
SPI_WORD_SIZE_GET(config->operation), config->frequency);
|
||||
} else {
|
||||
SPI_Open(dev_cfg->spi,
|
||||
(SPI_OP_MODE_GET(config->operation) == SPI_OP_MODE_SLAVE) ? SPI_SLAVE
|
||||
: SPI_MASTER,
|
||||
smode_tbl[mode],
|
||||
SPI_WORD_SIZE_GET(config->operation), config->frequency);
|
||||
}
|
||||
|
||||
/* Set Transfer LSB or MSB first */
|
||||
if ((config->operation) & SPI_TRANSFER_LSB) {
|
||||
SPI_SET_LSB_FIRST(dev_cfg->spi);
|
||||
} else {
|
||||
SPI_SET_MSB_FIRST(dev_cfg->spi);
|
||||
}
|
||||
|
||||
/* full/half duplex */
|
||||
if (config->operation & SPI_HALF_DUPLEX) {
|
||||
/* half duplex, which results in 3-wire usage */
|
||||
SPI_ENABLE_3WIRE_MODE(dev_cfg->spi);
|
||||
} else {
|
||||
/* full duplex */
|
||||
SPI_DISABLE_3WIRE_MODE(dev_cfg->spi);
|
||||
}
|
||||
|
||||
/* Active high CS logic */
|
||||
if (config->operation & SPI_CS_ACTIVE_HIGH) {
|
||||
SPI_SET_SS_HIGH(dev_cfg->spi);
|
||||
} else {
|
||||
SPI_SET_SS_LOW(dev_cfg->spi);
|
||||
}
|
||||
|
||||
/* Enable the automatic hardware slave select function. Select the SS pin and configure as
|
||||
* low-active.
|
||||
*/
|
||||
if (data->ctx.num_cs_gpios != 0) {
|
||||
SPI_EnableAutoSS(dev_cfg->spi, SPI_SS, SPI_SS_ACTIVE_LOW);
|
||||
} else {
|
||||
SPI_DisableAutoSS(dev_cfg->spi);
|
||||
}
|
||||
|
||||
/* Be able to set TX/RX FIFO threshold, for ex: SPI_SetFIFO(dev_cfg->spi, 2, 2) */
|
||||
|
||||
data->ctx.config = config;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spi_numaker_txrx(const struct device *dev)
|
||||
{
|
||||
struct spi_numaker_data *data = dev->data;
|
||||
const struct spi_numaker_config *dev_cfg = dev->config;
|
||||
struct spi_context *ctx = &data->ctx;
|
||||
uint32_t tx_frame, rx_frame;
|
||||
uint8_t word_size, spi_dfs;
|
||||
uint32_t time_out_cnt;
|
||||
|
||||
LOG_DBG("%s", __func__);
|
||||
word_size = SPI_WORD_SIZE_GET(ctx->config->operation);
|
||||
|
||||
switch (word_size) {
|
||||
case 8:
|
||||
spi_dfs = 1;
|
||||
break;
|
||||
case 16:
|
||||
spi_dfs = 2;
|
||||
break;
|
||||
case 24:
|
||||
spi_dfs = 3;
|
||||
break;
|
||||
case 32:
|
||||
spi_dfs = 4;
|
||||
break;
|
||||
default:
|
||||
spi_dfs = 0;
|
||||
LOG_ERR("Not support SPI WORD size as [%d] bits", word_size);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
LOG_DBG("%s -->word_size [%d]", __func__, word_size);
|
||||
|
||||
if (spi_context_tx_on(ctx)) {
|
||||
tx_frame = ((ctx->tx_buf == NULL) ? SPI_NUMAKER_TX_NOP
|
||||
: UNALIGNED_GET((uint8_t *)(data->ctx.tx_buf)));
|
||||
/* Write to TX register */
|
||||
SPI_WRITE_TX(dev_cfg->spi, tx_frame);
|
||||
spi_context_update_tx(ctx, spi_dfs, 1);
|
||||
|
||||
/* Check SPI busy status */
|
||||
time_out_cnt = SystemCoreClock; /* 1 second time-out */
|
||||
while (SPI_IS_BUSY(dev_cfg->spi)) {
|
||||
if (--time_out_cnt == 0) {
|
||||
LOG_ERR("Wait for SPI time-out");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DBG("%s --> TX [0x%x] done", __func__, tx_frame);
|
||||
}
|
||||
|
||||
/* Read received data */
|
||||
if (spi_context_rx_on(ctx)) {
|
||||
if (SPI_GET_RX_FIFO_COUNT(dev_cfg->spi) > 0) {
|
||||
rx_frame = SPI_READ_RX(dev_cfg->spi);
|
||||
if (ctx->rx_buf != NULL) {
|
||||
UNALIGNED_PUT(rx_frame, (uint8_t *)data->ctx.rx_buf);
|
||||
}
|
||||
spi_context_update_rx(ctx, spi_dfs, 1);
|
||||
LOG_DBG("%s --> RX [0x%x] done", __func__, rx_frame);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DBG("%s --> exit", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Remain TX/RX Data in spi_context TX/RX buffer */
|
||||
static bool spi_numaker_remain_words(struct spi_numaker_data *data)
|
||||
{
|
||||
return spi_context_tx_on(&data->ctx) || spi_context_rx_on(&data->ctx);
|
||||
}
|
||||
|
||||
static int spi_numaker_transceive(const struct device *dev, const struct spi_config *config,
|
||||
const struct spi_buf_set *tx_bufs,
|
||||
const struct spi_buf_set *rx_bufs)
|
||||
{
|
||||
struct spi_numaker_data *data = dev->data;
|
||||
struct spi_context *ctx = &data->ctx;
|
||||
const struct spi_numaker_config *dev_cfg = dev->config;
|
||||
int ret;
|
||||
|
||||
LOG_DBG("%s", __func__);
|
||||
spi_context_lock(ctx, false, NULL, NULL, config);
|
||||
ctx->config = config;
|
||||
|
||||
ret = spi_numaker_configure(dev, config);
|
||||
if (ret < 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
SPI_ENABLE(dev_cfg->spi);
|
||||
|
||||
spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1);
|
||||
|
||||
/* if cs is defined: software cs control, set active true */
|
||||
if (spi_cs_is_gpio(config)) {
|
||||
spi_context_cs_control(&data->ctx, true);
|
||||
}
|
||||
|
||||
/* transceive tx/rx data */
|
||||
do {
|
||||
ret = spi_numaker_txrx(dev);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
} while (spi_numaker_remain_words(data));
|
||||
|
||||
/* if cs is defined: software cs control, set active false */
|
||||
if (spi_cs_is_gpio(config)) {
|
||||
spi_context_cs_control(&data->ctx, false);
|
||||
}
|
||||
SPI_DISABLE(dev_cfg->spi);
|
||||
|
||||
done:
|
||||
spi_context_release(ctx, ret);
|
||||
LOG_DBG("%s --> [%d]", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int spi_numaker_release(const struct device *dev, const struct spi_config *config)
|
||||
{
|
||||
struct spi_numaker_data *data = dev->data;
|
||||
struct spi_context *ctx = &data->ctx;
|
||||
|
||||
if (!spi_context_configured(ctx, config)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
spi_context_unlock_unconditionally(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver_api spi_numaker_driver_api = {.transceive = spi_numaker_transceive,
|
||||
.release = spi_numaker_release};
|
||||
|
||||
static int spi_numaker_init(const struct device *dev)
|
||||
{
|
||||
struct spi_numaker_data *data = dev->data;
|
||||
const struct spi_numaker_config *dev_cfg = dev->config;
|
||||
int err = 0;
|
||||
struct numaker_scc_subsys scc_subsys;
|
||||
|
||||
SYS_UnlockReg();
|
||||
|
||||
/* CLK controller */
|
||||
memset(&scc_subsys, 0x00, sizeof(scc_subsys));
|
||||
scc_subsys.subsys_id = NUMAKER_SCC_SUBSYS_ID_PCC;
|
||||
scc_subsys.pcc.clk_modidx = dev_cfg->clk_modidx;
|
||||
scc_subsys.pcc.clk_src = dev_cfg->clk_src;
|
||||
scc_subsys.pcc.clk_div = dev_cfg->clk_div;
|
||||
|
||||
/* Equivalent to CLK_EnableModuleClock() */
|
||||
err = clock_control_on(dev_cfg->clk_dev, (clock_control_subsys_t)&scc_subsys);
|
||||
if (err != 0) {
|
||||
goto done;
|
||||
}
|
||||
/* Equivalent to CLK_SetModuleClock() */
|
||||
err = clock_control_configure(dev_cfg->clk_dev, (clock_control_subsys_t)&scc_subsys, NULL);
|
||||
if (err != 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
err = pinctrl_apply_state(dev_cfg->pincfg, PINCTRL_STATE_DEFAULT);
|
||||
if (err) {
|
||||
LOG_ERR("Failed to apply pinctrl state");
|
||||
goto done;
|
||||
}
|
||||
|
||||
err = spi_context_cs_configure_all(&data->ctx);
|
||||
if (err < 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
spi_context_unlock_unconditionally(&data->ctx);
|
||||
|
||||
/* Reset this module, same as BSP's SYS_ResetModule(id_rst) */
|
||||
if (!device_is_ready(dev_cfg->reset.dev)) {
|
||||
LOG_ERR("reset controller not ready");
|
||||
err = -ENODEV;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Reset SPI to default state */
|
||||
reset_line_toggle_dt(&dev_cfg->reset);
|
||||
|
||||
done:
|
||||
SYS_LockReg();
|
||||
return err;
|
||||
}
|
||||
|
||||
#define NUMAKER_SPI_INIT(inst) \
|
||||
PINCTRL_DT_INST_DEFINE(inst); \
|
||||
static struct spi_numaker_data spi_numaker_data_##inst = { \
|
||||
SPI_CONTEXT_INIT_LOCK(spi_numaker_data_##inst, ctx), \
|
||||
SPI_CONTEXT_INIT_SYNC(spi_numaker_data_##inst, ctx), \
|
||||
SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(inst), ctx)}; \
|
||||
static struct spi_numaker_config spi_numaker_config_##inst = { \
|
||||
.spi = (SPI_T *)DT_INST_REG_ADDR(inst), \
|
||||
.is_qspi = DT_INST_NODE_HAS_PROP(inst, qspi), \
|
||||
.reset = RESET_DT_SPEC_INST_GET(inst), \
|
||||
.clk_modidx = DT_INST_CLOCKS_CELL(inst, clock_module_index), \
|
||||
.clk_src = DT_INST_CLOCKS_CELL(inst, clock_source), \
|
||||
.clk_div = DT_INST_CLOCKS_CELL(inst, clock_divider), \
|
||||
.clk_dev = DEVICE_DT_GET(DT_PARENT(DT_INST_CLOCKS_CTLR(inst))), \
|
||||
.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
|
||||
}; \
|
||||
DEVICE_DT_INST_DEFINE(inst, &spi_numaker_init, NULL, &spi_numaker_data_##inst, \
|
||||
&spi_numaker_config_##inst, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, \
|
||||
&spi_numaker_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(NUMAKER_SPI_INIT)
|
|
@ -283,6 +283,127 @@
|
|||
status = "disabled";
|
||||
interrupts = <61 2>;
|
||||
};
|
||||
|
||||
spi0: spi@40061000 {
|
||||
compatible = "nuvoton,numaker-spi";
|
||||
reg = <0x40061000 0x6c>;
|
||||
interrupts = <23 0>;
|
||||
resets = <&rst NUMAKER_SPI0_RST>;
|
||||
clocks = <&pcc NUMAKER_SPI0_MODULE NUMAKER_CLK_CLKSEL2_SPI0SEL_HIRC 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi1: spi@40062000 {
|
||||
compatible = "nuvoton,numaker-spi";
|
||||
reg = <0x40062000 0x6c>;
|
||||
interrupts = <51 0>;
|
||||
resets = <&rst NUMAKER_SPI1_RST>;
|
||||
clocks = <&pcc NUMAKER_SPI1_MODULE NUMAKER_CLK_CLKSEL2_SPI1SEL_HIRC 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi2: spi@40063000 {
|
||||
compatible = "nuvoton,numaker-spi";
|
||||
reg = <0x40063000 0x6c>;
|
||||
interrupts = <52 0>;
|
||||
resets = <&rst NUMAKER_SPI2_RST>;
|
||||
clocks = <&pcc NUMAKER_SPI2_MODULE NUMAKER_CLK_CLKSEL3_SPI2SEL_HIRC 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi3: spi@40064000 {
|
||||
compatible = "nuvoton,numaker-spi";
|
||||
reg = <0x40064000 0x6c>;
|
||||
interrupts = <62 0>;
|
||||
resets = <&rst NUMAKER_SPI3_RST>;
|
||||
clocks = <&pcc NUMAKER_SPI3_MODULE NUMAKER_CLK_CLKSEL3_SPI3SEL_HIRC 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi4: spi@40065000 {
|
||||
compatible = "nuvoton,numaker-spi";
|
||||
reg = <0x40065000 0x6c>;
|
||||
interrupts = <63 0>;
|
||||
resets = <&rst NUMAKER_SPI4_RST>;
|
||||
clocks = <&pcc NUMAKER_SPI4_MODULE NUMAKER_CLK_CLKSEL4_SPI4SEL_HIRC 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi5: spi@40066000 {
|
||||
compatible = "nuvoton,numaker-spi";
|
||||
reg = <0x40066000 0x6c>;
|
||||
interrupts = <57 0>;
|
||||
resets = <&rst NUMAKER_SPI5_RST>;
|
||||
clocks = <&pcc NUMAKER_SPI5_MODULE NUMAKER_CLK_CLKSEL4_SPI5SEL_HIRC 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi6: spi@40067000 {
|
||||
compatible = "nuvoton,numaker-spi";
|
||||
reg = <0x40067000 0x6c>;
|
||||
interrupts = <70 0>;
|
||||
resets = <&rst NUMAKER_SPI6_RST>;
|
||||
clocks = <&pcc NUMAKER_SPI6_MODULE NUMAKER_CLK_CLKSEL4_SPI6SEL_HIRC 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi7: spi@40068000 {
|
||||
compatible = "nuvoton,numaker-spi";
|
||||
reg = <0x40068000 0x6c>;
|
||||
interrupts = <77 0>;
|
||||
resets = <&rst NUMAKER_SPI7_RST>;
|
||||
clocks = <&pcc NUMAKER_SPI7_MODULE NUMAKER_CLK_CLKSEL4_SPI7SEL_HIRC 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi8: spi@4006b000 {
|
||||
compatible = "nuvoton,numaker-spi";
|
||||
reg = <0x4006b000 0x6c>;
|
||||
interrupts = <108 0>;
|
||||
resets = <&rst NUMAKER_SPI8_RST>;
|
||||
clocks = <&pcc NUMAKER_SPI8_MODULE NUMAKER_CLK_CLKSEL4_SPI8SEL_HIRC 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi9: spi@4006c000 {
|
||||
compatible = "nuvoton,numaker-spi";
|
||||
reg = <0x4006c000 0x6c>;
|
||||
interrupts = <111 0>;
|
||||
resets = <&rst NUMAKER_SPI9_RST>;
|
||||
clocks = <&pcc NUMAKER_SPI9_MODULE NUMAKER_CLK_CLKSEL4_SPI9SEL_HIRC 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi10: spi@4006d000 {
|
||||
compatible = "nuvoton,numaker-spi";
|
||||
reg = <0x4006d000 0x6c>;
|
||||
interrupts = <119 0>;
|
||||
resets = <&rst NUMAKER_SPI10_RST>;
|
||||
clocks = <&pcc NUMAKER_SPI10_MODULE NUMAKER_CLK_CLKSEL4_SPI10SEL_HIRC 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
21
dts/bindings/spi/nuvoton,numaker-spi.yaml
Normal file
21
dts/bindings/spi/nuvoton,numaker-spi.yaml
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Copyright (c) 2023 Nuvoton Technology Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: Nuvoton, NuMaker SPI controller
|
||||
|
||||
compatible: "nuvoton,numaker-spi"
|
||||
|
||||
include: [spi-controller.yaml, reset-device.yaml, pinctrl-device.yaml]
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
||||
|
||||
interrupts:
|
||||
required: true
|
||||
|
||||
resets:
|
||||
required: true
|
||||
|
||||
clocks:
|
||||
required: true
|
Loading…
Add table
Add a link
Reference in a new issue