drivers: spi: rv32m1: Add driver for RV32M1 LPSPI
Add SPI driver and bindings for LPSPI peripheral for the RV32M1 SOC. Based heavily on the existing mcux LPSPI driver. Signed-off-by: Karsten Koenig <karsten.koenig.030@gmail.com>
This commit is contained in:
parent
e031477892
commit
ee2dd7322f
|
@ -162,6 +162,7 @@
|
|||
/drivers/ptp_clock/ @jukkar
|
||||
/drivers/spi/ @tbursztyka
|
||||
/drivers/spi/spi_ll_stm32.* @superna9999
|
||||
/drivers/spi/spi_rv32m1_lpspi* @karstenkoenig
|
||||
/drivers/timer/apic_timer.c @andrewboie
|
||||
/drivers/timer/cortex_m_systick.c @ioannisg
|
||||
/drivers/timer/altera_avalon_timer_hal.c @wentongwu
|
||||
|
|
|
@ -10,6 +10,7 @@ zephyr_library_sources_ifdef(CONFIG_SPI_MCUX_LPSPI spi_mcux_lpspi.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_SPI_SAM spi_sam.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SPI_SAM0 spi_sam0.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SPI_SIFIVE spi_sifive.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_SPI_RV32M1_LPSPI spi_rv32m1_lpspi.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_NRFX_SPI spi_nrfx_spi.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_NRFX_SPIM spi_nrfx_spim.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_NRFX_SPIS spi_nrfx_spis.c)
|
||||
|
|
|
@ -187,6 +187,8 @@ source "drivers/spi/Kconfig.mcux_dspi"
|
|||
|
||||
source "drivers/spi/Kconfig.mcux_lpspi"
|
||||
|
||||
source "drivers/spi/Kconfig.rv32m1_lpspi"
|
||||
|
||||
source "drivers/spi/Kconfig.sam"
|
||||
|
||||
source "drivers/spi/Kconfig.sam0"
|
||||
|
|
12
drivers/spi/Kconfig.rv32m1_lpspi
Normal file
12
drivers/spi/Kconfig.rv32m1_lpspi
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Kconfig - RV32M1 SPI
|
||||
#
|
||||
# Copyright (c) 2019, Karsten Koenig <karsten.koenig.030@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
config SPI_RV32M1_LPSPI
|
||||
bool "RV32M1 LPSPI driver"
|
||||
depends on HAS_RV32M1_LPSPI && CLOCK_CONTROL
|
||||
help
|
||||
Enable the RV32M1 LPSPI driver.
|
409
drivers/spi/spi_rv32m1_lpspi.c
Normal file
409
drivers/spi/spi_rv32m1_lpspi.c
Normal file
|
@ -0,0 +1,409 @@
|
|||
/*
|
||||
* Copyright (c) 2018, NXP
|
||||
*
|
||||
* Forked off the spi_mcux_lpi2c driver.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <drivers/spi.h>
|
||||
#include <drivers/clock_control.h>
|
||||
#include <fsl_lpspi.h>
|
||||
|
||||
#define LOG_LEVEL CONFIG_SPI_LOG_LEVEL
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(spi_rv32m1_lpspi);
|
||||
|
||||
#include "spi_context.h"
|
||||
|
||||
#define CHIP_SELECT_COUNT 4
|
||||
#define MAX_DATA_WIDTH 4096
|
||||
|
||||
struct spi_mcux_config {
|
||||
LPSPI_Type *base;
|
||||
char *clock_name;
|
||||
clock_control_subsys_t clock_subsys;
|
||||
clock_ip_name_t clock_ip_name;
|
||||
u32_t clock_ip_src;
|
||||
void (*irq_config_func)(struct device *dev);
|
||||
};
|
||||
|
||||
struct spi_mcux_data {
|
||||
lpspi_master_handle_t handle;
|
||||
struct spi_context ctx;
|
||||
size_t transfer_len;
|
||||
};
|
||||
|
||||
static void spi_mcux_transfer_next_packet(struct device *dev)
|
||||
{
|
||||
const struct spi_mcux_config *config = dev->config->config_info;
|
||||
struct spi_mcux_data *data = dev->driver_data;
|
||||
LPSPI_Type *base = config->base;
|
||||
struct spi_context *ctx = &data->ctx;
|
||||
lpspi_transfer_t transfer;
|
||||
status_t status;
|
||||
|
||||
if ((ctx->tx_len == 0) && (ctx->rx_len == 0)) {
|
||||
/* nothing left to rx or tx, we're done! */
|
||||
spi_context_cs_control(&data->ctx, false);
|
||||
spi_context_complete(&data->ctx, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
transfer.configFlags = kLPSPI_MasterPcsContinuous |
|
||||
(ctx->config->slave << LPSPI_MASTER_PCS_SHIFT);
|
||||
|
||||
if (ctx->tx_len == 0) {
|
||||
/* rx only, nothing to tx */
|
||||
transfer.txData = NULL;
|
||||
transfer.rxData = ctx->rx_buf;
|
||||
transfer.dataSize = ctx->rx_len;
|
||||
} else if (ctx->rx_len == 0) {
|
||||
/* tx only, nothing to rx */
|
||||
transfer.txData = (u8_t *) ctx->tx_buf;
|
||||
transfer.rxData = NULL;
|
||||
transfer.dataSize = ctx->tx_len;
|
||||
} else if (ctx->tx_len == ctx->rx_len) {
|
||||
/* rx and tx are the same length */
|
||||
transfer.txData = (u8_t *) ctx->tx_buf;
|
||||
transfer.rxData = ctx->rx_buf;
|
||||
transfer.dataSize = ctx->tx_len;
|
||||
} else if (ctx->tx_len > ctx->rx_len) {
|
||||
/* Break up the tx into multiple transfers so we don't have to
|
||||
* rx into a longer intermediate buffer. Leave chip select
|
||||
* active between transfers.
|
||||
*/
|
||||
transfer.txData = (u8_t *) ctx->tx_buf;
|
||||
transfer.rxData = ctx->rx_buf;
|
||||
transfer.dataSize = ctx->rx_len;
|
||||
transfer.configFlags |= kLPSPI_MasterPcsContinuous;
|
||||
} else {
|
||||
/* Break up the rx into multiple transfers so we don't have to
|
||||
* tx from a longer intermediate buffer. Leave chip select
|
||||
* active between transfers.
|
||||
*/
|
||||
transfer.txData = (u8_t *) ctx->tx_buf;
|
||||
transfer.rxData = ctx->rx_buf;
|
||||
transfer.dataSize = ctx->tx_len;
|
||||
transfer.configFlags |= kLPSPI_MasterPcsContinuous;
|
||||
}
|
||||
|
||||
if (!(ctx->tx_count <= 1 && ctx->rx_count <= 1)) {
|
||||
transfer.configFlags |= kLPSPI_MasterPcsContinuous;
|
||||
}
|
||||
|
||||
data->transfer_len = transfer.dataSize;
|
||||
status = LPSPI_MasterTransferNonBlocking(base, &data->handle,
|
||||
&transfer);
|
||||
if (status != kStatus_Success) {
|
||||
LOG_ERR("Transfer could not start");
|
||||
}
|
||||
}
|
||||
|
||||
static void spi_mcux_isr(void *arg)
|
||||
{
|
||||
struct device *dev = (struct device *)arg;
|
||||
const struct spi_mcux_config *config = dev->config->config_info;
|
||||
struct spi_mcux_data *data = dev->driver_data;
|
||||
LPSPI_Type *base = config->base;
|
||||
|
||||
LPSPI_MasterTransferHandleIRQ(base, &data->handle);
|
||||
}
|
||||
|
||||
static void spi_mcux_master_transfer_callback(LPSPI_Type *base,
|
||||
lpspi_master_handle_t *handle, status_t status, void *userData)
|
||||
{
|
||||
struct device *dev = userData;
|
||||
struct spi_mcux_data *data = dev->driver_data;
|
||||
|
||||
spi_context_update_tx(&data->ctx, 1, data->transfer_len);
|
||||
spi_context_update_rx(&data->ctx, 1, data->transfer_len);
|
||||
|
||||
spi_mcux_transfer_next_packet(dev);
|
||||
}
|
||||
|
||||
static int spi_mcux_configure(struct device *dev,
|
||||
const struct spi_config *spi_cfg)
|
||||
{
|
||||
const struct spi_mcux_config *config = dev->config->config_info;
|
||||
struct spi_mcux_data *data = dev->driver_data;
|
||||
LPSPI_Type *base = config->base;
|
||||
lpspi_master_config_t master_config;
|
||||
struct device *clock_dev;
|
||||
u32_t clock_freq;
|
||||
u32_t word_size;
|
||||
|
||||
if (spi_context_configured(&data->ctx, spi_cfg)) {
|
||||
/* This configuration is already in use */
|
||||
return 0;
|
||||
}
|
||||
|
||||
LPSPI_MasterGetDefaultConfig(&master_config);
|
||||
|
||||
if (spi_cfg->slave > CHIP_SELECT_COUNT) {
|
||||
LOG_ERR("Slave %d is greater than %d",
|
||||
spi_cfg->slave,
|
||||
CHIP_SELECT_COUNT);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
word_size = SPI_WORD_SIZE_GET(spi_cfg->operation);
|
||||
if (word_size > MAX_DATA_WIDTH) {
|
||||
LOG_ERR("Word size %d is greater than %d",
|
||||
word_size, MAX_DATA_WIDTH);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
master_config.bitsPerFrame = word_size;
|
||||
|
||||
master_config.cpol =
|
||||
(SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPOL)
|
||||
? kLPSPI_ClockPolarityActiveLow
|
||||
: kLPSPI_ClockPolarityActiveHigh;
|
||||
|
||||
master_config.cpha =
|
||||
(SPI_MODE_GET(spi_cfg->operation) & SPI_MODE_CPHA)
|
||||
? kLPSPI_ClockPhaseSecondEdge
|
||||
: kLPSPI_ClockPhaseFirstEdge;
|
||||
|
||||
master_config.direction =
|
||||
(spi_cfg->operation & SPI_TRANSFER_LSB)
|
||||
? kLPSPI_LsbFirst
|
||||
: kLPSPI_MsbFirst;
|
||||
|
||||
master_config.baudRate = spi_cfg->frequency;
|
||||
|
||||
clock_dev = device_get_binding(config->clock_name);
|
||||
if (clock_dev == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (clock_control_get_rate(clock_dev, config->clock_subsys,
|
||||
&clock_freq)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
LPSPI_MasterInit(base, &master_config, clock_freq);
|
||||
|
||||
LPSPI_MasterTransferCreateHandle(base, &data->handle,
|
||||
spi_mcux_master_transfer_callback, dev);
|
||||
|
||||
data->ctx.config = spi_cfg;
|
||||
spi_context_cs_configure(&data->ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int transceive(struct device *dev,
|
||||
const struct spi_config *spi_cfg,
|
||||
const struct spi_buf_set *tx_bufs,
|
||||
const struct spi_buf_set *rx_bufs,
|
||||
bool asynchronous,
|
||||
struct k_poll_signal *signal)
|
||||
{
|
||||
struct spi_mcux_data *data = dev->driver_data;
|
||||
int ret;
|
||||
|
||||
spi_context_lock(&data->ctx, asynchronous, signal);
|
||||
|
||||
ret = spi_mcux_configure(dev, spi_cfg);
|
||||
if (ret) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1);
|
||||
|
||||
spi_context_cs_control(&data->ctx, true);
|
||||
|
||||
spi_mcux_transfer_next_packet(dev);
|
||||
|
||||
ret = spi_context_wait_for_completion(&data->ctx);
|
||||
out:
|
||||
spi_context_release(&data->ctx, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int spi_mcux_transceive(struct device *dev,
|
||||
const struct spi_config *spi_cfg,
|
||||
const struct spi_buf_set *tx_bufs,
|
||||
const struct spi_buf_set *rx_bufs)
|
||||
{
|
||||
return transceive(dev, spi_cfg, tx_bufs, rx_bufs, false, NULL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPI_ASYNC
|
||||
static int spi_mcux_transceive_async(struct device *dev,
|
||||
const struct spi_config *spi_cfg,
|
||||
const struct spi_buf_set *tx_bufs,
|
||||
const struct spi_buf_set *rx_bufs,
|
||||
struct k_poll_signal *async)
|
||||
{
|
||||
return transceive(dev, spi_cfg, tx_bufs, rx_bufs, true, async);
|
||||
}
|
||||
#endif /* CONFIG_SPI_ASYNC */
|
||||
|
||||
static int spi_mcux_release(struct device *dev,
|
||||
const struct spi_config *spi_cfg)
|
||||
{
|
||||
struct spi_mcux_data *data = dev->driver_data;
|
||||
|
||||
spi_context_unlock_unconditionally(&data->ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spi_mcux_init(struct device *dev)
|
||||
{
|
||||
const struct spi_mcux_config *config = dev->config->config_info;
|
||||
struct spi_mcux_data *data = dev->driver_data;
|
||||
|
||||
CLOCK_SetIpSrc(config->clock_ip_name, config->clock_ip_src);
|
||||
|
||||
config->irq_config_func(dev);
|
||||
|
||||
spi_context_unlock_unconditionally(&data->ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_driver_api spi_mcux_driver_api = {
|
||||
.transceive = spi_mcux_transceive,
|
||||
#ifdef CONFIG_SPI_ASYNC
|
||||
.transceive_async = spi_mcux_transceive_async,
|
||||
#endif
|
||||
.release = spi_mcux_release,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SPI_0
|
||||
static void spi_mcux_config_func_0(struct device *dev);
|
||||
|
||||
static const struct spi_mcux_config spi_mcux_config_0 = {
|
||||
.base = (LPSPI_Type *) DT_OPENISA_RV32M1_LPSPI_SPI_0_BASE_ADDRESS,
|
||||
.clock_name = DT_OPENISA_RV32M1_LPSPI_SPI_0_CLOCK_CONTROLLER,
|
||||
.clock_subsys = (clock_control_subsys_t)
|
||||
DT_OPENISA_RV32M1_LPSPI_SPI_0_CLOCK_NAME,
|
||||
.irq_config_func = spi_mcux_config_func_0,
|
||||
.clock_ip_name = kCLOCK_Lpspi0,
|
||||
.clock_ip_src = kCLOCK_IpSrcFircAsync,
|
||||
};
|
||||
|
||||
static struct spi_mcux_data spi_mcux_data_0 = {
|
||||
SPI_CONTEXT_INIT_LOCK(spi_mcux_data_0, ctx),
|
||||
SPI_CONTEXT_INIT_SYNC(spi_mcux_data_0, ctx),
|
||||
};
|
||||
|
||||
DEVICE_AND_API_INIT(spi_mcux_0, DT_OPENISA_RV32M1_LPSPI_SPI_0_LABEL,
|
||||
&spi_mcux_init, &spi_mcux_data_0, &spi_mcux_config_0,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
|
||||
&spi_mcux_driver_api);
|
||||
|
||||
static void spi_mcux_config_func_0(struct device *dev)
|
||||
{
|
||||
IRQ_CONNECT(DT_OPENISA_RV32M1_LPSPI_SPI_0_IRQ_0,
|
||||
DT_OPENISA_RV32M1_LPSPI_SPI_0_IRQ_0_PRIORITY,
|
||||
spi_mcux_isr, DEVICE_GET(spi_mcux_0), 0);
|
||||
|
||||
irq_enable(DT_OPENISA_RV32M1_LPSPI_SPI_0_IRQ_0);
|
||||
}
|
||||
#endif /* SPI_0 */
|
||||
|
||||
#ifdef CONFIG_SPI_1
|
||||
static void spi_mcux_config_func_1(struct device *dev);
|
||||
|
||||
static const struct spi_mcux_config spi_mcux_config_1 = {
|
||||
.base = (LPSPI_Type *) DT_OPENISA_RV32M1_LPSPI_SPI_1_BASE_ADDRESS,
|
||||
.clock_name = DT_OPENISA_RV32M1_LPSPI_SPI_1_CLOCK_CONTROLLER,
|
||||
.clock_subsys = (clock_control_subsys_t)
|
||||
DT_OPENISA_RV32M1_LPSPI_SPI_1_CLOCK_NAME,
|
||||
.irq_config_func = spi_mcux_config_func_1,
|
||||
.clock_ip_name = kCLOCK_Lpspi1,
|
||||
.clock_ip_src = kCLOCK_IpSrcFircAsync,
|
||||
};
|
||||
|
||||
static struct spi_mcux_data spi_mcux_data_1 = {
|
||||
SPI_CONTEXT_INIT_LOCK(spi_mcux_data_1, ctx),
|
||||
SPI_CONTEXT_INIT_SYNC(spi_mcux_data_1, ctx),
|
||||
};
|
||||
|
||||
DEVICE_AND_API_INIT(spi_mcux_1, DT_OPENISA_RV32M1_LPSPI_SPI_1_LABEL,
|
||||
&spi_mcux_init, &spi_mcux_data_1, &spi_mcux_config_1,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
|
||||
&spi_mcux_driver_api);
|
||||
|
||||
static void spi_mcux_config_func_1(struct device *dev)
|
||||
{
|
||||
IRQ_CONNECT(DT_OPENISA_RV32M1_LPSPI_SPI_1_IRQ_0,
|
||||
DT_OPENISA_RV32M1_LPSPI_SPI_1_IRQ_0_PRIORITY,
|
||||
spi_mcux_isr, DEVICE_GET(spi_mcux_1), 0);
|
||||
|
||||
irq_enable(DT_OPENISA_RV32M1_LPSPI_SPI_1_IRQ_0);
|
||||
}
|
||||
#endif /* SPI_1 */
|
||||
|
||||
#ifdef CONFIG_SPI_2
|
||||
static void spi_mcux_config_func_2(struct device *dev);
|
||||
|
||||
static const struct spi_mcux_config spi_mcux_config_2 = {
|
||||
.base = (LPSPI_Type *) DT_OPENISA_RV32M1_LPSPI_SPI_2_BASE_ADDRESS,
|
||||
.clock_name = DT_OPENISA_RV32M1_LPSPI_SPI_2_CLOCK_CONTROLLER,
|
||||
.clock_subsys = (clock_control_subsys_t)
|
||||
DT_OPENISA_RV32M1_LPSPI_SPI_2_CLOCK_NAME,
|
||||
.irq_config_func = spi_mcux_config_func_2,
|
||||
.clock_ip_name = kCLOCK_Lpspi2,
|
||||
.clock_ip_src = kCLOCK_IpSrcFircAsync,
|
||||
};
|
||||
|
||||
static struct spi_mcux_data spi_mcux_data_2 = {
|
||||
SPI_CONTEXT_INIT_LOCK(spi_mcux_data_2, ctx),
|
||||
SPI_CONTEXT_INIT_SYNC(spi_mcux_data_2, ctx),
|
||||
};
|
||||
|
||||
DEVICE_AND_API_INIT(spi_mcux_2, DT_OPENISA_RV32M1_LPSPI_SPI_2_LABEL,
|
||||
&spi_mcux_init, &spi_mcux_data_2, &spi_mcux_config_2,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
|
||||
&spi_mcux_driver_api);
|
||||
|
||||
static void spi_mcux_config_func_2(struct device *dev)
|
||||
{
|
||||
IRQ_CONNECT(DT_OPENISA_RV32M1_LPSPI_SPI_2_IRQ_0,
|
||||
DT_OPENISA_RV32M1_LPSPI_SPI_2_IRQ_0_PRIORITY,
|
||||
spi_mcux_isr, DEVICE_GET(spi_mcux_2), 0);
|
||||
|
||||
irq_enable(DT_OPENISA_RV32M1_LPSPI_SPI_2_IRQ_0);
|
||||
}
|
||||
#endif /* SPI_2 */
|
||||
|
||||
#ifdef CONFIG_SPI_3
|
||||
static void spi_mcux_config_func_3(struct device *dev);
|
||||
|
||||
static const struct spi_mcux_config spi_mcux_config_3 = {
|
||||
.base = (LPSPI_Type *) DT_OPENISA_RV32M1_LPSPI_SPI_3_BASE_ADDRESS,
|
||||
.clock_name = DT_OPENISA_RV32M1_LPSPI_SPI_3_CLOCK_CONTROLLER,
|
||||
.clock_subsys = (clock_control_subsys_t)
|
||||
DT_OPENISA_RV32M1_LPSPI_SPI_3_CLOCK_NAME,
|
||||
.irq_config_func = spi_mcux_config_func_3,
|
||||
.clock_ip_name = kCLOCK_Lpspi3,
|
||||
.clock_ip_src = kCLOCK_IpSrcFircAsync,
|
||||
};
|
||||
|
||||
static struct spi_mcux_data spi_mcux_data_3 = {
|
||||
SPI_CONTEXT_INIT_LOCK(spi_mcux_data_3, ctx),
|
||||
SPI_CONTEXT_INIT_SYNC(spi_mcux_data_3, ctx),
|
||||
};
|
||||
|
||||
DEVICE_AND_API_INIT(spi_mcux_3, DT_OPENISA_RV32M1_LPSPI_SPI_3_LABEL,
|
||||
&spi_mcux_init, &spi_mcux_data_3, &spi_mcux_config_3,
|
||||
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
|
||||
&spi_mcux_driver_api);
|
||||
|
||||
static void spi_mcux_config_func_3(struct device *dev)
|
||||
{
|
||||
IRQ_CONNECT(DT_OPENISA_RV32M1_LPSPI_SPI_3_IRQ_0,
|
||||
DT_OPENISA_RV32M1_LPSPI_SPI_3_IRQ_0_PRIORITY,
|
||||
spi_mcux_isr, DEVICE_GET(spi_mcux_3), 0);
|
||||
|
||||
irq_enable(DT_OPENISA_RV32M1_LPSPI_SPI_3_IRQ_0);
|
||||
}
|
||||
#endif /* CONFIG_SPI_3 */
|
21
dts/bindings/spi/openisa,rv32m1-lpspi.yaml
Normal file
21
dts/bindings/spi/openisa,rv32m1-lpspi.yaml
Normal file
|
@ -0,0 +1,21 @@
|
|||
#
|
||||
# Copyright (c) 2019, Karsten Koenig <karsten.koenig.030@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
title: OpenISA LPSPI
|
||||
|
||||
description: >
|
||||
This binding gives a base representation of the OpenISA LPSPI controller
|
||||
|
||||
compatible: "openisa,rv32m1-lpspi"
|
||||
|
||||
include: spi-controller.yaml
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
||||
|
||||
interrupts:
|
||||
required: true
|
|
@ -32,6 +32,10 @@
|
|||
i2c-1 = &i2c1;
|
||||
i2c-2 = &i2c2;
|
||||
i2c-3 = &i2c3;
|
||||
spi-0 = &spi0;
|
||||
spi-1 = &spi1;
|
||||
spi-2 = &spi2;
|
||||
spi-3 = &spi3;
|
||||
};
|
||||
|
||||
cpus {
|
||||
|
@ -443,6 +447,46 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
spi0: spi@4003f000 {
|
||||
compatible = "openisa,rv32m1-lpspi";
|
||||
reg = <0x4003f000 0x78>;
|
||||
label = "SPI_0";
|
||||
status = "disabled";
|
||||
clocks = <&pcc0 0xfc>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
spi1: spi@40040000 {
|
||||
compatible = "openisa,rv32m1-lpspi";
|
||||
reg = <0x40040000 0x78>;
|
||||
label = "SPI_1";
|
||||
status = "disabled";
|
||||
clocks = <&pcc0 0x100>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
spi2: spi@40041000 {
|
||||
compatible = "openisa,rv32m1-lpspi";
|
||||
reg = <0x40041000 0x78>;
|
||||
label = "SPI_2";
|
||||
status = "disabled";
|
||||
clocks = <&pcc0 0x104>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
spi3: spi@41035000 {
|
||||
compatible = "openisa,rv32m1-lpspi";
|
||||
reg = <0x41035000 0x78>;
|
||||
label = "SPI_3";
|
||||
status = "disabled";
|
||||
clocks = <&pcc1 0xd4>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
flash-controller@40023000 {
|
||||
compatible = "openisa,rv32m1-ftfe";
|
||||
label = "FLASH_CTRL";
|
||||
|
|
|
@ -170,3 +170,23 @@
|
|||
interrupt-parent = <&intmux0_ch1>;
|
||||
interrupts = <24>;
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
interrupt-parent = <&event0>;
|
||||
interrupts = <13>;
|
||||
};
|
||||
|
||||
&spi1 {
|
||||
interrupt-parent = <&event0>;
|
||||
interrupts = <14>;
|
||||
};
|
||||
|
||||
&spi2 {
|
||||
interrupt-parent = <&intmux0_ch1>;
|
||||
interrupts = <12>;
|
||||
};
|
||||
|
||||
&spi3 {
|
||||
interrupt-parent = <&intmux0_ch1>;
|
||||
interrupts = <25>;
|
||||
};
|
||||
|
|
|
@ -169,3 +169,23 @@
|
|||
interrupt-parent = <&event1>;
|
||||
interrupts = <16>;
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
interrupt-parent = <&intmux1_ch0>;
|
||||
interrupts = <18>;
|
||||
};
|
||||
|
||||
&spi1 {
|
||||
interrupt-parent = <&intmux1_ch0>;
|
||||
interrupts = <19>;
|
||||
};
|
||||
|
||||
&spi2 {
|
||||
interrupt-parent = <&intmux1_ch0>;
|
||||
interrupts = <20>;
|
||||
};
|
||||
|
||||
&spi3 {
|
||||
interrupt-parent = <&event1>;
|
||||
interrupts = <19>;
|
||||
};
|
||||
|
|
|
@ -15,6 +15,11 @@ config HAS_RV32M1_LPI2C
|
|||
help
|
||||
Set if the low power i2c (LPI2C) module is present in the SoC.
|
||||
|
||||
config HAS_RV32M1_LPSPI
|
||||
bool
|
||||
help
|
||||
Set if the low power spi (LPSPI) module is present in the SoC.
|
||||
|
||||
config HAS_RV32M1_FTFX
|
||||
bool
|
||||
help
|
||||
|
|
|
@ -161,6 +161,14 @@ config I2C_RV32M1_LPI2C
|
|||
|
||||
endif # I2C
|
||||
|
||||
if SPI
|
||||
|
||||
config SPI_RV32M1_LPSPI
|
||||
default y
|
||||
|
||||
endif # SPI
|
||||
|
||||
|
||||
if FLASH
|
||||
|
||||
config SOC_FLASH_RV32M1
|
||||
|
|
|
@ -10,6 +10,7 @@ config SOC_OPENISA_RV32M1_RISCV32
|
|||
select XIP
|
||||
select HAS_RV32M1_LPUART
|
||||
select HAS_RV32M1_LPI2C
|
||||
select HAS_RV32M1_LPSPI
|
||||
select ATOMIC_OPERATIONS_C
|
||||
select VEGA_SDK_HAL
|
||||
select RISCV_SOC_INTERRUPT_INIT
|
||||
|
|
2
west.yml
2
west.yml
|
@ -47,7 +47,7 @@ manifest:
|
|||
revision: e0bfd6f253ca6a5e87b6f53a8bb317bd6f483511
|
||||
path: modules/hal/nordic
|
||||
- name: hal_openisa
|
||||
revision: be5c01f86c96500def5079bcc58d2baefdffb6c8
|
||||
revision: 0cbbf29f1523fe2970e57622bd79d9b115ca84e5
|
||||
path: modules/hal/openisa
|
||||
- name: hal_microchip
|
||||
revision: 85302959c0c659311cf90ac51d133e5ce19c9288
|
||||
|
|
Loading…
Reference in a new issue